Task 9  Task 9: Subroutines and Functions  Task 9


Very often while writing programs you'll run into cases where you'll have to execute the same set of steps, over and over again. In those cases it wouldn’t make sense to rewrite the same statements multiple times. That’s where subroutines and functions come in handy, allowing you to reuse a piece of source code as many times as you wish.

A subroutine is a portion of code within a larger program that usually does something very specific and can be called from anywhere in the program. A function acts exactly the same as a subroutine except for an important difference; functions are expected to return a value after they are called. Let's discuss subroutines first and then move onto functions later in this task.


-- Subroutines --

Subroutines are identified by a name that follows the SUB statement and are terminated by the END SUB statement. Type in the following example program that we'll use to investigate how subroutines work.

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM Flip% '     flips between the values of 0 and 1
DIM x% '        used as x coordinate counter for drawing
DIM y% '        used as y coordinate counter for drawing
DIM RedWhite% ' value for either white or red color

'----------------------------
'- Main Program Begins Here -
'----------------------------

_TITLE "Flag" '                                        give window a title
SCREEN 12 '                                            enter a graphics screen
FOR y% = 0 TO 467 STEP 36 '                            loop in steps of 36
    IF Flip% = 0 THEN '                                is current value 0?
        RedWhite% = 4 '                                yes, set color to red
    ELSE '                                             no, must be 1
        RedWhite% = 15 '                               set color to white
    END IF
    LINE (0, y%)-(639, y% + 35), RedWhite%, BF '       draw colored stripe
    Flip% = 1 - Flip% '                                flip value of variable
NEXT y%
LINE (0, 0)-(309, 251), 1, BF '                        draw blue banner
FOR y% = 25 TO 225 STEP 50 '                           loop in steps of 50
    FOR x% = 30 TO 280 STEP 50 '                       loop in steps of 50
        LINE (x% - 10, y% - 3)-(x% + 10, y% - 3), 15 ' draw a solid star
        LINE -(x% - 7, y% + 7), 15
        LINE -(x%, y% - 10), 15
        LINE -(x% + 7, y% + 7), 15
        LINE -(x% - 10, y% - 3), 15
        PAINT (x%, y%), 15, 15
        PAINT (x% - 5, y% - 1), 15, 15
        PAINT (x% + 5, y% - 1), 15, 15
        PAINT (x%, y% - 4), 15, 15
        PAINT (x% - 3, y% + 3), 15, 15
        PAINT (x% + 3, y% + 3), 15, 15
    NEXT x%
NEXT y%
FOR y% = 50 TO 200 STEP 50 '                           loop in steps of 50
    FOR x% = 55 TO 255 STEP 50 '                       loop in steps of 50
        LINE (x% - 10, y% - 3)-(x% + 10, y% - 3), 15 ' draw a solid star
        LINE -(x% - 7, y% + 7), 15
        LINE -(x%, y% - 10), 15
        LINE -(x% + 7, y% + 7), 15
        LINE -(x% - 10, y% - 3), 15
        PAINT (x%, y%), 15, 15
        PAINT (x% - 5, y% - 1), 15, 15
        PAINT (x% + 5, y% - 1), 15, 15
        PAINT (x%, y% - 4), 15, 15
        PAINT (x% - 3, y% + 3), 15, 15
        PAINT (x% + 3, y% + 3), 15, 15
    NEXT x%
NEXT y%
SLEEP '                                                wait for a key press
SYSTEM '                                               return to Windows

The program above is a perfect example of where a subroutine can reduce the size of the cource code. As you can see, the following lines of code are redundant:

        LINE (x% - 10, y% - 3)-(x% + 10, y% - 3), 15 ' draw a solid star
        LINE -(x% - 7, y% + 7), 15
        LINE -(x%, y% - 10), 15
        LINE -(x% + 7, y% + 7), 15
        LINE -(x% - 10, y% - 3), 15
        PAINT (x%, y%), 15, 15
        PAINT (x% - 5, y% - 1), 15, 15
        PAINT (x% + 5, y% - 1), 15, 15
        PAINT (x%, y% - 4), 15, 15
        PAINT (x% - 3, y% + 3), 15, 15
        PAINT (x% + 3, y% + 3), 15, 15


These 11 lines of code are used in two different locations. A subroutine can be created to contain these lines of code and then called upon when needed. Let's create a subroutine called Star that can be called when needed. You can name a subroutine or function anything you wish but you must follow the same naming rules as used with variables described in Task 5.

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM Flip% '     flips between the values of 0 and 1
DIM x% '        used as x coordinate counter for drawing
DIM y% '        used as y coordinate counter for drawing
DIM RedWhite% ' value for either white or red color

'----------------------------
'- Main Program Begins Here -
'----------------------------

_TITLE "Flag" '                                  give window a title
SCREEN 12 '                                      enter a graphics screen
FOR y% = 0 TO 467 STEP 36 '                      loop in steps of 36
    IF Flip% = 0 THEN '                          is current value 0?
        RedWhite% = 4 '                          yes, set color to red
    ELSE '                                       no, must be 1
        RedWhite% = 15 '                         set color to white
    END IF
    LINE (0, y%)-(639, y% + 35), RedWhite%, BF ' draw colored stripe
    Flip% = 1 - Flip% '                          flip value of variable
NEXT y%
LINE (0, 0)-(309, 251), 1, BF '                  draw blue banner
FOR y% = 25 TO 225 STEP 50 '                     loop in steps of 50
    FOR x% = 30 TO 280 STEP 50 '                 loop in steps of 50
        Star x%, y% '                            draw star at x,y coordinate
    NEXT x%
NEXT y%
FOR y% = 50 TO 200 STEP 50 '                     loop in steps of 50
    FOR x% = 55 TO 255 STEP 50 '                 loop in steps of 50
        Star x%, y% '                            draw star at x,y coordinate
    NEXT x%
NEXT y%
SLEEP

'-----------------------------------
'- Function and Subroutine section -
'-----------------------------------

SUB Star (sx%, sy%)
'
'* draws a solid star at x,y coordinate *
'
LINE (sx% - 10, sy% - 3)-(sx% + 10, sy% - 3), 15
LINE -(sx% - 7, sy% + 7), 15
LINE -(sx%, sy% - 10), 15
LINE -(sx% + 7, sy% + 7), 15
LINE -(sx% - 10, sy% - 3), 15
PAINT (sx%, sy%), 15, 15
PAINT (sx% - 5, sy% - 1), 15, 15
PAINT (sx% + 5, sy% - 1), 15, 15
PAINT (sx%, sy% - 4), 15, 15
PAINT (sx% - 3, sy% + 3), 15, 15
PAINT (sx% + 3, sy% + 3), 15, 15

END SUB

The main program section of the code has been greatly reduced in size because each of the 11 lines of code originally in this section have been replaced with the following statement:

        Star x%, y% '                            draw star at x,y coordinate

When QB64 encounters this statement it executes the lines of code in the subroutine associated with it:

SUB Star (sx%, sy%)
'
'* draws a solid star at x,y coordinate *
'
LINE (sx% - 10, sy% - 3)-(sx% + 10, sy% - 3), 15
LINE -(sx% - 7, sy% + 7), 15
LINE -(sx%, sy% - 10), 15
LINE -(sx% + 7, sy% + 7), 15
LINE -(sx% - 10, sy% - 3), 15
PAINT (sx%, y%), 15, 15
PAINT (sx% - 5, sy% - 1), 15, 15
PAINT (sx% + 5, sy% - 1), 15, 15
PAINT (sx%, sy% - 4), 15, 15
PAINT (sx% - 3, sy% + 3), 15, 15
PAINT (sx% + 3, sy% + 3), 15, 15

END SUB


Think of a subroutine as a mini program within your program that can be called upon when needed. Another way to think of a subroutine is a custom command that you created that can be used when needed. Variables that you declare in the main declaration section however will not be seen by your subroutines. Any variables declared outside of the subroutine must have their values passed into the subroutine in order to see them. The line that created the subroutine Star allows for two values to be passed in:

SUB Star (sx%, sy%)

In order to call the subroutine from somewhere else in the code you must now supply two values along with it:

Star x%, y%

These values can come from variables as we did with this code in the line above or actual numeric values such as:

Star 100, 50

Now this is where it gets a little complicated. The variables sx% and sy% contained within the subroutine are known as local variables. These variables are only seen within the subroutine but, if you were change the value of either one of the variables the new values would get passed back to the line of code that called the subroutine. So, in this program's case the value in either x%, y% or both would get changed. Let's play around with a much smaller program that illustrates what this means.

DIM Test%

Test% = 10
PRINT "Value of Test% before entering subroutine"; Test%
PRINT
PRINT "Subroutine called ..."
MySub Test%
PRINT
PRINT "Value of Test% is now"; Test%; "because the subroutine changed it!"


SUB MySub (Value%)

Value% = 99

END SUB

Initially the value of Test% is set to 10. When the subroutine is called the value contained in Test% is passed to the subroutine's local variable Value%. Since the value of Value% was changed inside the subroutine that change is reflected back to Test% in the calling line of code, therefore changing the value in Test% as well. This behavior is by design as it allows a programmer the ability to pass back changes that subroutines make. The reason this behavior happens is because a subroutine references, or points to, the value in the memory location (RAM) of the variable used to pass the value in. When the value get changed in the subroutine what actually happens is the memory location itself changes. Since the calling variable references, or points to, this same memory location its value is also changed. If you want to ensure that values do not get accidently changed and passed back you can declare local variables using DIM inside the subroutine like so:

DIM Test%

Test% = 10
PRINT "Value of Test% before entering subroutine"; Test%
PRINT
PRINT "Subroutine called ..."
MySub Test%
PRINT
PRINT "Value of Test% is still"; Test%


SUB MySub (Value%)

DIM LocalValue% ' a local variable

LocalValue% = Value%
LocalValue% = 99

END SUB

In this example the value of Test% never changes because inside the subroutine we copy its value to another local variable contained within the subroutine itself. Changing this second local variable has no effect on the calling variable and ensures accidental value changes will not occur.

TIP: Many a sleepness night have been spent by programmers tracking down variables that have changed unexpectedly somewhere in their code. If this is happening to you, and your code is using subroutines or functions that have values passed in by use of variables, this is the first place to check.

Another method of passing variables to subroutines is to make any variable you wish to use in the subroutine global in nature. Let's make another modification to our example code to see this in action:


DIM SHARED Test% ' a global variable

Test% = 10
PRINT "Value of Test% before entering subroutine"; Test%
PRINT
PRINT "Subroutine called ..."
MySub
PRINT
PRINT "Value of Test% is now"; Test%; "because it is global"


SUB MySub ()

Test% = 99

END SUB

In this example we added the SHARED statement to the DIM statement in the first line of code turning the variable Test% into a global variable. A global variable is a variable that is seen by the entire program which includes subroutines and functions. Go ahead and remove the SHARED statement from the first line and execute the program again. This time the variable Test% did not change it's value. This is because you now actually have two local variables with the same name. Test% in the main program section is local to any code outside of subroutines and functions and Test% contained inside the subroutine is local only to the subroutine. Variables with the same name within different subroutines and functions is actually a very common practice of programmers and is perfectly acceptable to perform. In many of my programs I use the generic variable Count% in my subroutines and functions when I need a simple FOR...NEXT loop variable to count specific values for me. KeyPress$ is another common variable name I use when I need to test for a keystroke within subroutines and functions.

Believe it or not there is a third way to pass variables to subroutines and functions. One again, let's modify the example code to see this:


DIM Test% ' local to the main program section

Test% = 10
PRINT "Value of Test% before entering subroutine"; Test%
PRINT
PRINT "Subroutine called ..."
MySub
PRINT
PRINT "Value of Test% is now"; Test%; "because it is shared inside the subroutine."


SUB MySub ()

SHARED Test%

Test% = 99

END SUB

This time Test% is still declared at the beginning of the code as a local variable to the main program section. However, inside the subroutine we use the SHARED statement again with the name of the local variable to bring it inside the subroutine. With this method you can pick and choose only those subroutines and functions that actually need access to a particular variable.

It's up to you as the programmer as to which method you will use in any particular instance to share variable values inside of subroutines and functions. In some cases it makes sense to pass values in through the subroutine's name, Star x%, y%, in other cases it may make sense to make the variable global, DIM SHARED Test% and yet other instances you may want to pick and choose only those needed, SHARED Test%. You'll find that in many of the example programs I have included with this course I favor the third option of declaring all variables local then choosing only those I want to share with certain subroutines and functions. Again, the method you choose most often will be the one you feel most comfortable with as there is no right or wrong way to handle this.


-- Functions --

Functions behave exactly like subroutines when it comes to sharing and passing variable values to them. There are two key differences however. The first is that functions are identified by a name that follows the FUNCTION statement and are terminated by the END FUNCTION statement. The second is that the function's name behaves as a variable containing a value that can be passed back from the function itself. Type in the following program to get an understanding of this:

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM a!
DIM b!
DIM UserString1$
DIM UserString2$

'----------------------------
'- Main Program Begins Here -
'----------------------------

PRINT
INPUT "Enter a number       > ", a!
INPUT "Enter another number > ", b!
PRINT
PRINT a!; "+"; b!; "="; Add!(a!, b!)
PRINT a!; "-"; b!; "="; Subtract!(a!, b!)
PRINT a!; "*"; b!; "="; Multiply!(a!, b!)
PRINT
INPUT "Type something      > ", UserString1$
INPUT "Type something else > ", UserString2$
PRINT
PRINT "Concatenation resulted in: "; Concatenate$(UserString1$, UserString2$)

'-----------------------------------
'- Function and Subroutine section -
'-----------------------------------

FUNCTION Add! (num1!, num2!)

Add! = num1! + num2!

END FUNCTION

'-----------------------------------

FUNCTION Subtract! (num1!, num2!)

Subtract! = num1! - num2!

END FUNCTION

'-----------------------------------

FUNCTION Multiply! (num1!, num2!)

Multiply! = num1! * num2!

END FUNCTION

'-----------------------------------

FUNCTION Concatenate$ (s1$, s2$)

Concatenate$ = s1$ + s2$

END FUNCTION

'-----------------------------------

Let's examine this function named Add! in the example program:

FUNCTION Add! (num1!, num2!)

Add! = num1! + num2!

END FUNCTION


With a function the name of the function is treated like a variable, therefore a type identifier is needed at the end of it to determine the type of value it will hold. In this function's case we added the exclamation point (!) indicating that the function's name will hold single precision real numbers. To call the function in the program you treat it as you would any other variable. The following lines of code will call the function:

PRINT Add!(10, 20)
Solution! = Add!(10, 20)
Complex! = Add!(x%, y%) + Add!(a%, b%)


As you can see in the example lines of code above the function is simply treated as a variable. However, this special variable can pass information into the function and information is returned back. The way you return information back is to use the functions's name inside the function itself and set it equal to a value:

Add! = num1! + num2!

Whatever is contained after the equals sign is returned back to the calling line of code. Here is another sample program that uses two functions to solve for the Pythagorean Theorem. (You may copy and paste this one into your IDE as it is quite long).


'-------------------------------------------------------
'Description: Solves graphically the Pythagorean Theorem
'Author     : Terry Ritchie
'Date       : 11/02/13
'Version    : 1.0
'Rights     : Open source, free to modify and distribute
'Terms      : Original author's name must remain intact
'-------------------------------------------------------

'--------------------------------
'- Variable Declaration Section -
'--------------------------------

DIM a!, b!, c! ' the lengths of the sides of the triangle
DIM Answer! '    the answer to the problem presented by the user
DIM KeyPress$ '  any key that the user presses when asked to execute program again

'----------------------------
'- Main Program Begins Here -
'----------------------------

_TITLE "Solve Pythagorean Theorem" '                               give window a title
SCREEN 12 '                                                        enter a graphics screen
DO '                                                               begin main program loop here
    CLS '                                                          clear the screen
    LOCATE 2, 9 '                                                  position text cursor
    COLOR 7 '                                                      set text color to white
    PRINT "This program will solve the Pythagorean Theorem "; '    inform user of program purpose
    PRINT "(A"; CHR$(253); " + B"; CHR$(253); " = C"; CHR$(253); ")" ' character 253 in ASCII is power of 2 symbol
    COLOR 15 '                                                     set text color to bright white
    LOCATE 9, 28 '                                                 position text cursor
    PRINT "c =" '                                                  print text
    COLOR 14 '                                                     set text color to yellow
    LOCATE 10, 55 '                                                position text cursor
    PRINT "b =" '                                                  print text
    COLOR 12 '                                                     set text color to bright red
    LOCATE 17, 37 '                                                position text cursor
    PRINT "a =" '                                                  print text
    LINE (219, 250)-(419, 50), 15 '                                draw triangle's bright white hypotenuse
    LINE -(419, 250), 14 '                                         draw triangle's yellow leg
    LINE -(219, 250), 12 '                                         draw trianlge's bright red leg
    LINE (409, 250)-(409, 240), 12 '                               draw 90 degree indicator
    LINE -(419, 240), 14
    COLOR 7 '                                                      set text color to white
    LOCATE 19, 24 '                                                position text cursor
    PRINT "Enter the values for a, b and c." '                     inform user of what to do
    LOCATE 20, 24 '                                                position text cursor
    PRINT "Enter 0 to solve for that length." '                    print more information for user
    a! = AskFor!(22, 27, "a", 12, 17, 40) '                        ask user for value of side a leg
    b! = AskFor!(23, 27, "b", 14, 10, 58) '                        ask user for value of side b leg
    c! = AskFor!(24, 27, "c", 15, 9, 31) '                         ask user for value of side c hypotenuse
    Answer! = SolvePythagoras!(a!, b!, c!) '                       solve for Pathagorean Theorem
    IF Answer! = -1 THEN '                                         is the solution -1?
        LOCATE 26, 16 '                                            yes, unsolvable, position text cursor
        COLOR 15 '                                                 set text color to bright white
        PRINT "ERROR: Triangle not possible with values provided" 'inform user that problem can't be solved
    ELSEIF Answer! = 0 THEN '                                      is the solution 0?
        LOCATE 26, 22 '                                            yes, unsolvable, position text cursor
        COLOR 15 '                                                 set text color to bright white
        PRINT "ERROR: Unsolvable! Too many unkowns!" '             inform user that problem can't be solved
    ELSEIF a! = 0 THEN '                                           was side a to be solved for?
        LOCATE 17, 40 '                                            yes, position text cursor
        COLOR 12 '                                                 set text color to bright red
        PRINT Answer! '                                            print value of side a
    ELSEIF b! = 0 THEN '                                           no, was side b to be solved for?
        LOCATE 10, 58 '                                            yes, position text cursor
        COLOR 14 '                                                 set text color to yellow
        PRINT Answer! '                                            print value of side b
    ELSE '                                                         no, side c is to be solved for
        LOCATE 9, 31 '                                             position text cursor
        COLOR 15 '                                                 set text color to bright white
        PRINT Answer! '                                            print value of side c
    END IF
    COLOR 10 '                                                     set text color to bright green
    LOCATE 28, 16 '                                                position text cursor
    PRINT "Press ESC key to exit or any key to solve again." '     give user instructions
    DO '                                                           begin keyboard loop here
        KeyPress$ = INKEY$ '                                       save any keystroke pressed
        _LIMIT 5 '                                                 limit to 5 loops per second
    LOOP UNTIL KeyPress$ <> "" '                                   stop loop when a key was pressed
LOOP UNTIL KeyPress$ = CHR$(27) '                                  stop main loop if ESC key pressed
SYSTEM '                                                           return to Windows

'-----------------------------------
'- Function and Subroutine section -
'-----------------------------------

'--------------------------------------------------------------------------------------------------

FUNCTION AskFor! (x%, y%, L$, c%, px%, py%)
'
'* asks for a value and returns the result *
'* updates screen with answers given       *
'
'x%, y%   = text coordinate to place question at
'L$       = the name of the letter to ask the value of
'c%       = the color of the letter (line on triangle)
'px%, py% = text coordinate to place value at

DIM Value! ' the value the user supplies

LOCATE x%, y% '                                   position text cursor on screen
COLOR 7 '                                         set text color to white
PRINT "Enter the value for "; '                   place text message on screen
COLOR c% '                                        set text color to color passed in
PRINT L$; '                                       place letter on screen passed in
COLOR 7 '                                         set text color back to white
INPUT " > ", Value! '                             ask user for a value
LOCATE px%, py% '                                 position text cursor on screen
COLOR c% '                                        set text color to color passed in
IF Value! = 0 THEN PRINT " ?" ELSE PRINT Value! ' print value or ? depending on user input
AskFor! = Value! '                                return to calling statement value user typed in

END FUNCTION

'--------------------------------------------------------------------------------------------------

FUNCTION SolvePythagoras! (SideA!, SideB!, SideC!)
'
'* Solves the Pythagorean Theorem given two of three triangle sides.    *
'* This function will return a value of 0 if more than one side of the  *
'* triangle is asked to be solved, which is impossible with Pythagoras. *
'* A value of -1 will be returned if the problem is unsolvable due to   *
'* impossible number pairs given for sides a&c or b&c.                  *
'
'SideA! = leg length of triangle        (value of 0 to solve)
'SideB! = leg length of trinagle        (value of 0 to solve)
'SideC! = hypotenuse length of triangle (value of 0 to solve)
'
IF SideA! = 0 THEN '                                          is side a to be solved?
    IF (SideB! <> 0) AND (SideC! <> 0) THEN '                 yes, is side a only side asked to solve?
        IF SideC! <= SideB! THEN '                            are numbers possible for right triangle?
            SolvePythagoras! = -1 '                           no, return the error
        ELSE '                                                no, these numbers are valid
            SolvePythagoras! = SQR(SideC! ^ 2 - SideB! ^ 2) ' return solution for side a
        END IF
    END IF
ELSEIF SideB! = 0 THEN '                                      no, is side b to be solved?
    IF (SideA! <> 0) AND (SideC! <> 0) THEN '                 yes, is side b only side asked to solve?
        IF SideC! <= SideA THEN '                             are numbers possible for a right triangle?
            SolvePythagoras! = -1 '                           no, return the error
        ELSE '                                                no, these numbers are valid
            SolvePythagoras! = SQR(SideC! ^ 2 - SideA! ^ 2) ' return solution for side b
        END IF
    END IF
ELSEIF SideC! = 0 THEN '                                      no, is side c to be solved?
    IF (SideA! <> 0) AND (SideB! <> 0) THEN '                 yes, is side c only side asked to solve?
        SolvePythagoras! = SQR(SideA! ^ 2 + SideB! ^ 2) '     yes, return solution for side c
    END IF
ELSE '                                                        no, user entered 0 for more than one side!
    SolvePythagoras! = 0 '                                    return 0 due to too many unknowns
END IF

END FUNCTION

'--------------------------------------------------------------------------------------------------

Pythagoras
Figure 1 - Told you QB64 could do your homework!

Don't let the length of the previous example program scare you. Take each line one at a time and you'll see that most of the code we have already covered. Also, notice the generous use of remarks throughout the code explaining exactly how the program operates. Make sure to get in the habit of remarking your code very well for both your benefit and the benefit of other programmers reading your sorce code. In the function SolvePythagoras! however there are two mathematical related items that are new, SQR() and ^ (exponent or "to the power of"). SQR() is a built-in QB64 function that returns the square root of a number and ^ raises the exponent of a number, for example 2 ^ 3 = 8 (2 times 2 times 2). There is an upcoming task devoted to the various mathematical functions contained in QB64.

Note: The choice of using the Pythagorean Theorem in the previous example was not by coincidence. The Pythagorean Theorem is the basis for simple collision detection in games because it can be used to determine the distance between two objects on an x,y coordinate system. An upcoming task will deal with various basic algorithms used in game programming.

-- Your Turn --

In an earlier task you created a program that converts inches to mm. Do this again but this time create a function called Inches2mm!(Inches!) that does the conversion and returns the result. Save your program as I_TO_M2.bas when finished. Your output screen should like this:

Converter
Figure 2 - A handy dandy little converter


-- COMMAND REFERENCE --


Commands learned in previous tasks:

PRINT
INPUT
DIM
REM or '
CONST
TIME$
VAL()
IF...THEN
AND
END
GOTO
SELECT CASE...END SELECT
CASE
TO
IS
CASE ELSE
colon ( : )
FOR...NEXT
STEP
CLS
SLEEP
_DELAY
SYSTEM
DO...LOOP UNTIL (and variations)
WHILE...WEND
SCREEN
LINE
CIRCLE
PAINT
PSET

New commands introduced in this task:

SUB
END SUB
FUNCTION
END FUNCTION
SHARED
SQR()
^ (exponent)

Concepts learned in previous tasks:

execute
statement
expression
literal string
syntax error
variables
type declarations
literal strings
concatenation
integers
long integers
single precision
double precision
strings
null strings
reserved words
operators ( +, -, *, / )
declare
constant
relational operators
functions
nesting
order of operations
Boolean
conditions
indenting
loops
labels
frame rate
controlled loops
conditional loops
Monochrome
Grayscale
pixels
bits per pixel
radian
counter-clockwise
aspect ratio
algorithm

New concepts introduced in this task:

subroutine
function
local variables
RAM
global variables
Pythagorean Theorem