;-------------------------------------------------------------------------------
;
;   ;-------------------------------;
;   ;   Routines                    ;
;   ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;
;
; Copy and paste as you see fit.
;
;-------------------------------------------------------------------------------
;
; Remember how to generate random numbers?
;
    Number = Rand ( 10 )
;
; The Rand thingy is actually called a function.
;
; With functions you can
; for example divide your program in
; constructive blocks.
;
; But that's not all :P
;
; If you have to call a certain part
; of code zillions of times,
; you can put it inside a function
; for some easy function calls. (eh?)
;
; Suppose you have a piece of code
; for drawing some text on screen.
;
    Color 255 , 255 , 255
    Write "> "
    Color 255 , 64 , 128
    Print "Let's gooo!"
;
; You can put this inside a function
; so you won't have to copy and paste
; it everytime you want to call it.
;
    Function DrawTheText ()

        Color 255 , 255 , 255
        Write "> "
        Color 255 , 64 , 128
        Print "Let's gooo!"

    End Function
;
; And then you can call it like this:
;
    DrawTheText
;
; So now everything inside the function
; is called and then Blitz will continue
; with anything under the function call.
;
;           +--------------+
;           |              |
;   ------> |  Function    | ------>
;           |              |
;           +--------------+
;
; Yes, it's a bit like a loop.
; As it goes into the loop.
; Only it doesn't loop :P
;
; It's also a bit like a Type definition.
; When you define a function you just define it.
;
;   |   +------------------------+ <---+
;   |   |                        |     |
;   |   |  Function              |     |
;   |   |       DrawTheText      |     |
;   |   |                        |     |
;   |   +------------------------+     |
;   |               |                  |
;   v               |                  |
;                   |                  |
;   DrawTheText -----------------------+
;                   |
;   <---------------+
;
; And that's all there's to it! :P
;   - But you can't specify a number!
; Hold your horses :P
;
;-------------------------------------------------------------------------------
;
; I know the Global and Local keyword
; have been constantly bugging you.
; So allow me to explain
; what you've been waiting for :)
;
; You remember that Local variables
; are only visible to the current routine.
; And Global variables are visible
; everywhere in the program.
;   - What does that mean?
; When we create a Local variable
; inside a function, like this:
;
    Function CountToTen ()

        Local Iterator%

        For Iterator = 1 To 10
        Next

    End Function
;
; It will only be visible (or existent)
; inside that same function.
;
;     +-+---------------------------------------+
;     | |                                       |
;     | |   Main routine                        |
;     | |                                       |
;     | |         +-+------------------------------+
;     | |         | |                              |
;     | |         | |   Sub routine                |
;     | |         | |                              |
;     | |         | | <---- Local Iterator%        |
;     | |         | |                              |
;     | |         +-+------------------------------+
;     | |                                       |
;     +-+---------------------------------------+
;
; You'll also remember that by default
; all variables used for the first time
; are in fact Local.
;
; So removing the Local Iterator line
; will have no effect on the program.
;
    Function CountToTen ()

        For Iterator = 1 To 10
        Next

    End Function
;
; Defining your variables before they are used
; will however improve readability of the code.
;
; But as always,
; that's all up to the programmer ;)
;
; Global variables however,
; can only be defined in the base code.
;   - Where's that?
; E.g. not in a function.
; For example, right here:
;
    Global Integer%
;
; You can now access this variable
; anywhere in the main code
; as well as in any function.
;
;     +-+---------------------------------------+
;     | |                                       |
;     | |   Main routine                        | <--------+
;     | |                                       |          |
;     | |       Global Integer% ---------------------------+
;     | |                                       |          |
;     | |         +-+------------------------------+       |
;     | |         | |                              |       |
;     | |         | |   Sub routine                | <-----+
;     | |         | |                              |       |
;     | |         +-+------------------------------+       |
;     | |                                       |          |
;     | |                                       | <--------+
;     | |                                       |
;     +-+---------------------------------------+
;
; So be careful with naming your variables.
;   - Why?
; In case you have a local variable
; in a function with the same name
; as a global variable,
; the local variable will get priority
; inside the function.
;   - Say what?
; You see we have defined a
; Global variable named Integer.
;
; Now we define another variable,
; a Local variable with the same name
; inside a function.
;
    Function DoSomethingWithInteger ()
        Local Integer%

        Integer = 1000
    End Function
;
; Now let's call the function
; and see what happens.
;
    DoSomethingWithInteger
;
; Did the Global variable change?
;
    Print Integer
;
; No! Blitz will make the
; Local variable more important
; than the Global variable;
;
;     +-+---------------------------------------+
;     | |                                       |
;     | |   Main routine                        | <--------+
;     | |                                       |          |
;     | |       Global Integer% ---------------------------+
;     | |                                       |          |
;     | |         +-+------------------------------+       |
;     | |         | |                              |       |
;     | |         | |   Sub routine                |       |
;     | |         | |                              | \ /   |
;     | |         | | <---- Local Integer%         |  X <--+
;     | |         | |                              | / \   |
;     | |         +-+------------------------------+       |
;     | |                                       |          |
;     | |                                       | <--------+
;     | |                                       |
;     +-+---------------------------------------+
;
;-------------------------------------------------------------------------------
;
; When you define a Local variable
; in the main code
; it will only be accessible
; from the main code.
;
    Local Value%      ; Local Integer
;
    Function AttemptToAccessValue ()
        Value = -1
    End Function
;
    AttemptToAccessValue
;
    Print Value
;
;     +-+---------------------------------------+
;     | |                                       |
;     | |   Main routine                        |
;     | |                                       |
;     | | <---- Local Value%                    |
;     | |                                       |
;     | |         +-+------------------------------+
;     | |         | |                              |
;     | |         | |   Sub routine                |
;     | |         | |                              |
;     | |         | | <---- Local Value%           |
;     | |         | |                              |
;     | |         +-+------------------------------+
;     | |                                       |
;     +-+---------------------------------------+
;
; Inside the function above
; the variable Value
; will be created as
; just another Local variable
; visible only from within
; that same function.
;
; So you can actually consider
; the main routine to be a
; sub routine (function)
; that is run anyway.
;
;-------------------------------------------------------------------------------
;
; As with loops,
; you can combine functions.
;
;           +--------------+
;           |              |
;   ------> |  Function 1  | ------>
;           |              |
;           +--------------+
;                  |
;                  |
;                  |
;                  |
;                 \|/
;           +--------------+
;           |              |
;           |  Function 2  |
;           |              |
;           +--------------+
;
    Function RunFirst ()
        RunNext
    End Function

    Function RunNext ()
        Print "Ok"
    End Function

    RunFirst
;
;   |   +-----------------------+ <---------.
;   |   |                       |           |
;   |   |  Function             |           | In
;   |   |           RunNext     |           |
;   |   |                       |           |
;   |   +-----------------------+ ----------|-----.
;   |                                       |     |
;   |   +-----------------------+ <---.     |     | Out
;   |   |                       |     |     |     |
;   |   |  Function             |     | In  |     |
;   |   |           RunFirst    |     |     |     |
;   |   |                       |     |     |     |
;   |   |.-'^`-._.-'^`-._.-'^`-.|     |     |     |
;   |   |                       |     |     |     |
;   |   |  RunNext -------------------|-----'     |
;   |   |                       |     |           |
;   |   |  <--------------------|-----------------'
;   |   |                       |     |
;   |   +-----------------------+     |
;   v               | Out             |
;                   |                 |
;   RunFirst -------------------------'
;                   |
;   <---------------+
;
;-------------------------------------------------------------------------------
;
;   - What about specifying a number?
; Yes, you may have been wondering
; about those brackets () behind
; the function declaration.
;
; As with Rand () you can specify a value.
; This is called a parameter,
; but you probably already knew that :o)
; The Rand function also returns a value.
;
; I'll show you the syntax for such a function.
;
;   Function [Name] ( [Parameters] )
;
;       [Variables]
;
;       [Actions]
;
;       Return [Value]
;
;   End Function
;
; It's basically the same as before.
; Only adding one or more parameters
; as well as a Return command.
;
; Here's an example of a function
; that takes one parameter:
;
    Function PrintMe ( Value )
        Print Value
    End Function
;
; Now we have defined the function
; we can call it, like this:
;
    PrintMe 100
;
; And the number 100 should
; end up on your screen.
;
;           +-----------------------+
;           |                       |
;   ------> |  Function             | ------>
;           |           PrintMe     |
;           |                       |
;           |.-'^`-._.-'^`-._.-'^`-.|
;           |                       |
;   100 --> |         Value         |
;           |                       |
;   In      +-----------------------+
;                       |
;                       |
;                      \|/
;
;                     Print
;
; Now an example of returning a value:
;
    Function ReturnMe ()
        Return 100
    End Function
;
; Then we can call it like this:
;
    Value = ReturnMe ()
;
;           +-----------------------+
;           |                       |
;   ------> |  Function             | ------>
;           |           ReturnMe    |
;           |                       |
;           |.-'^`-._.-'^`-._.-'^`-.|
;           |                       |
;           |         Value         | --> 100
;           |                       |
;           +-----------------------+     Out
;
; Let's create a function which
; returns a random value of our choice.
; Basically the same as the Rand function
; but with a twist.
;
    Function RandomTwist ( Our_Choice )

        Value = Rand ( -Our_Choice , Our_Choice )

        Return Value

    End Function
;
; Let's run it.
;
    RandomTwist 10
;
; Oh dear.
; Maybe it's better if we
; assign it to a variable.
;
    Value = RandomTwist ( 10 )
;
; Note the brackets.
; When the function returns a value,
; the brackets have to be included.
;
; Can you tell me in what range
; our Value is?
;
; It should be [-10..10],
; so let's take a look.
;
    Print Value
    WaitKey
;
; Satisfied? :)
;
; Let's fill an array with
; randomly twisted numbers.
;
    Dim Values( 20 )
;
    For Which = 1 To 20
        Values( Which ) = RandomTwist ( 10 )
    Next
;
; Now take a look at what we generated.
;
    Print "-----"
    For Which = 1 To 20
        Print Values( Which )
    Next
    WaitKey
;
; By default a value of 0 (False)
; is returned when no Return is used.
; At least, with integers :)
;   - Integers?
; Yes, all variables are
; by default Integer, remember?
;
;-------------------------------------------------------------------------------
;
; Remember that arrays are Global?
;
    Function ClearValues ()
        Dim Values( 20 )
    End Function
;
; You can erase the Values array
; inside the function
; so long as the array has been
; defined before the function.
; Otherwise Blitz won't see it.
;
;     +-+---------------------------------------+
;     | |                                       |
;     | |   Main routine                        | <--------+
;     | |                                       |          |
;     | |       Dim Values( 0 ) ---------------------------+
;     | |                                       |          |
;     | |         +-+------------------------------+       |
;     | |         | |                              |       |
;     | |         | |   Sub routine                |       |
;     | |         | |                              |       |
;     | |         | |       Dim Values( 20 )       | <-----+
;     | |         | |                              |       |
;     | |         +-+------------------------------+       |
;     | |                                       |          |
;     | |                                       | <--------+
;     | |                                       |
;     +-+---------------------------------------+
;
;-------------------------------------------------------------------------------
;
; You want more parameters?
; You got 'em!
;
    Function ToThePowerOf ( x , y )
        Return x ^ y
    End Function
;
; As you can see, you can stack
; pretty much anything you want
; behind the Return command.
;
; That goes for anywhere
; in your code as well.
;
; And I didn't mean code-wise;
;
    For Iterator = 1 To 10 Color 255 , 255 , 255 Write "" Next
;
; Even though that's possible as well :P
;
; I meant evaluation-wise:
;
    Value = Rand ( x ^ Rand ( x ^ y ) * ToThePowerOf ( x , Rand ( x ^ y ) ) )
;
; So you can for example
; make a function return
; something like that.
;
; Here:
;
    Function AmazingResults ( x , y )
        Return Rand ( x ^ Rand ( x ^ y ) * ToThePowerOf ( x , Rand ( x ^ y ) ) )
    End Function
;
; Let's call the function
; with some stuff as parameters
; and see what it generates.
;
    Print "-----"
    Print AmazingResults ( 3 , 2 )
;
; You can see that even here
; Print is actually also a bit
; like a function.
;
; AmazingResults returns a value
; which is then passed onto
; Print as a parameter.
;
; In fact, just like we did before
; by stacking it behind the Return.
;
    Function Return_AmazingResults ( x , y )
        Return AmazingResults( x , y )
    End Function
;
; Not very useful,
; but I guess you get the idea:
;
; Stack all you want :)
;
;-------------------------------------------------------------------------------
;
; The parameters you specify
; actually become local variables
; inside the function.
;
; You can even change the value of parameters,
; but they only exist for as long as the function lasts.
;
; Example:
;
    Function FoolAround ( a , b , c )

        ; Mix it up.
        a = b
        b = c
        c = a

        ; See what we got.
        Print "a: " + a
        Print "b: " + b
        Print "c: " + c

    End Function
;
; Now see what happens.
;
    FoolAround 1 , 2 , 3
;
;-------------------------------------------------------------------------------
;
; Let's try some other parameter variable types.
;
    Function ParametersAreLocals( a# , b# , c# , d# , e# )

        ; Mix it all up (in a crazy way).
        remember# = c
        c = ( a + b ) / ( d + e )
        a = remember * 2
        b = remember * remember
        d = 2 / remember
        e = Sqr ( remember )    ; Math function for square root.

        ; Return.. erm.. something.
        Return ( a - b ) ^ ( d - e ) * c

    End Function
;
; As you can see,
; you can use any type of variable as parameter.
; Integers, floats, strings and yes, even pointers.
;
; Let's call the function.
;
    Print ParametersAreLocals( 1 , 2 , 3 , 4 , 5 )
;
; Because Print doesn't return any value
; you don't have to include the brackets.
;
; Even though you could also write it as:
;
    Print ( Parameters )
;
; Again, this is just personal preference :)
;
;-------------------------------------------------------------------------------
;
; You can also change the return type of a function.
; As by default the return type is, again, integer.
;
    Function SquareRoot# ( Value )
        Return Sqr ( Value )
    End Function
;
; So this function returns a floating point value.
;
; Syntax:
;
;   Function [Name] [Type] ( [Parameters] )
;
; Here's an example function
; with some schematics to display
; the specific variables used.
;
    Function TextOutLine ( Pos_X% , Pos_Y% , Message$ )
        Local X%
        Local Y%

        Color 255 , 255 , 255
        For X = -1 To 1
            For Y = -1 To 1
                Text Pos_X + X , Pos_Y + Y , Message
            Next
        Next
        Color 0 , 0 , 0
        Text Pos_X , Pos_Y , Message
    End Function
;
;     +-------------------+--------------------------+
;     |                   |  (Integer)  Pos_X        |
;     |  External         |  (Integer)  Pos_Y        |
;     |                   |  (String)   Message$     |
;     +-------------------+--------------------------+
;     |                   |  (Integer)  X            |
;     |  Internal         |  (Integer)  Y            |
;     |                   |                          |
;     +-------------------+--------------------------+
;     | Function Variables for TextOutline           |
;     +----------------------------------------------+
;
;     +------------------------+---------------------+
;     |                        |  Pos_X   (Integer)  |
;   ---->   Input Parameters   |  Pos_Y   (Integer)  |
;     |                        |  Message (String)   |
;     +------------------------+---------------------+
;     |                                              |
;   <----   Output Parameter      (Integer)          |
;     |                                              |
;     +----------------------------------------------+
;     | Function Parameters for TextOutline          |
;     +----------------------------------------------+
;
; That's right,
; even though it returns
; a value of type Integer,
; it is unused.
;
; So if you try to put
; the result in a variable,
; it will equal zero (False).
;
; Let's call the function
; just for illustration.
;
    TextOutline 100 , 100 , "OUTLINE"
    WaitKey
    Color 255 , 255 , 255       ; Reset color to white
;
;-------------------------------------------------------------------------------
;
; Time for some more variable types.
; I mean, you've seen integer, floating point
; and string variable type parameters.
; But not pointers.
;
; Suppose you have an enemy ship somewhere.
;
    Type EnemyShip
        ; Position on screen
        Field LocationX
        Field LocationY
    End Type
;
    Somewhere.EnemyShip = New EnemyShip
    Somewhere\LocationX = 100
    Somewhere\LocationY = 100
;
; And you want to delete it
; using a function.
;
    Function WipeItOut ( What.EnemyShip )
        Delete What
    End Function
;
; Then just call it.
;
    WipeItOut Somewhere
;
; And that's all there's to it! :P
;
; You can also return a pointer from a function.
;
; If you take the enemyship creation code from up there
; and stash it in a function, here's what you'll get:
;
    Function NewEnemyShip ()
        Somewhere.EnemyShip = New EnemyShip
        Somewhere\LocationX = 100
        Somewhere\LocationY = 100
    End Function
;
; Okay, but actually I meant
; returning the pointer Somewhere.
;
; You remember how to return a float, right?
;
;   Function SquareRoot# ( Value )
;
; Functions returning pointers are
; not so different from regular variables.
;
    Function CreateEnemyShip.EnemyShip ( WhereX , WhereY )
        Local Something.EnemyShip

        Something = New EnemyShip
        Something\LocationX = WhereX
        Something\LocationY = WhereY

        Return Something
    End Function
;
; And while we're at it,
; accepting 2 parameters
; to put the enemy somewhere.
;
; Now we can create an enemy like this:
;
    nme.EnemyShip = CreateEnemyShip ( 100 , 100 )
;
; But also like this:
;
    CreateEnemyShip 100 , 100
;
; If you don't specify a return value,
; e.g. not using the Return command,
; and the return type is a pointer,
; a Null pointer will be returned. (eh?)
;
    Function ReturnNothing.EnemyShip ()
    End Function
;
    nme = ReturnNothing ()
    If nme = Null
        Print "Nothin'"
    End If
;
; Just like with integers
; where False is returned.
; And floats as well.
; With strings however,
; literally nothing is returned.
; E.g. ("").
;
;-------------------------------------------------------------------------------
;
; When you pass a variable as parameter,
; the variable itself does not change, right?
;
    Function DoSomething_WithInteger ( AnyInteger% )
        AnyInteger = AnyInteger + 1
    End Function
;
    Integer = 0
    DoSomething_WithInteger Integer
    Print Integer
;
; It should be 0,
; because AnyInteger is a new variable,
; which contains only the value of Integer.
;
; Actually it's the same with pointers.
;
    Type Any
        Field Thing
    End Type
;
    Function DoSomething_WithPointer ( Pointer.Any )
        Pointer\Thing = 1337
        Pointer = Null
    End Function
;
; What happens here?
;
; Let's find out.
;
    Pointer.Any = New Any
    DoSomething_WithPointer Pointer
;
; Is Pointer pointing to nothing?
;
    If Pointer = Null
        Print "Yep"
    Else
        Print "Nope"
    End If
;
; If it's pointing to something,
; what's in it?
;
    Print Pointer\Thing
;
; See if you can play around with this some more.
; It can quickly help to understand in which ways
; pointers can be combined with functions.
;
;-------------------------------------------------------------------------------
;
; In case you want to return multiple variables,
; you can also use objects (pointers) for that.
;
; Suppose you have a player,
;
    Const Sex_Female = -1
    Const Sex_Male   =  0

    Type Player
        Field Sex
        Field PosX
        Field PosY
    End Type
;
    Local What.Player

    What = New Player
    What\Sex = Sex_Female
    What\PosX = 100
    What\PosY = 100
;
; but you don't know where she is.
;
    What = Null
;
; And you want a function to locate her.
;
    Type Location
        Field X
        Field Y
    End Type
;
    Function FindHer.Location ()
        Local Looking.Player
        Local Where.Location

        ; Find her.
        Looking = First Player

        ; Is it her?
        If Looking\Sex <> Sex_Female
            ; If not, abort!
            Return Null
        End If

        ; Locate her.
        Where = New Location
        Where\X = Looking\PosX
        Where\Y = Looking\PosY

        Return Where
    End Function
;
; Now locate her.
;
    Exact.Location = FindHer ()
;
; See where she is.
;
    Print "X: " + Exact\X + " Y: " + Exact\Y
;
; Ofcourse you could also just return her
; instead of her location.
; The above is, as always,
; just for illustration :P
;
; Let's try that for a male player.
;
    Function GrabHim.Player ()
        Local Male.Player

        Male = First Player
        If Male\Sex = Yes
            Return Male
        End If
    End Function
;
;-------------------------------------------------------------------------------
;
; What about some commands like Text
; where you have optional parameters?
;
; Like optional brackets there's a way
; to make parameters just as optional.
;
    Function GiveMeSugar ( HowMuch = 1 )
        Return HowMuch
    End Function
;
; If you don't specify a parameter,
; you will get 1 sugar.
;
    Print GiveMeSugar ()
;
; Don't forget the brackets though :)
; We're still returning a value.
;
; Here's another example.
;
    Const Nothing    = 0
    Const Anything   = 1
    Const More       = 2
    Const MoreLikeIt = 3
    Const Alot       = 4
    Const Most       = 5
    Const AlmostAll  = 6
    Const Everything = 7
;
    Function WhatDoWeWant$ ( Something = Nothing )
        Select Something
            Case Nothing
                Return "Zip"
            Case Anything
                Return "Here's a little something: " + Rand ( 10 )
            Case More
                Return "Getting greedy eh? :P"
            Case MoreLikeIt
                Return "You like that?"
            Case Alot
                Return "That's too much for you, mister!"
            Case Most
                Return "Hahaha! You wish!"
            Case AlmostAll
                Return "You feeling lucky?"
            Case Everything
                Return "Don't let it go to your head, kid."
        End Select
    End Function
;
; Yes, the default value (Nothing)
; has to be constant.
;
; Just like the size of BlitzArrays[tm].
;
    Print WhatDoWeWant ()
    Print WhatDoWeWant ( Rand( 0 , 7 ) )
;
;-------------------------------------------------------------------------------
;
; Actually there's another type of parameter you can use.
; It's a BlitzArray[tm].
;
    Const Elements = 1000
;
    Function SetElement ( AnyArray[ Elements ] , Element , Value )
        AnyArray[ Element ] = Value
    End Function
;
; The only big limitation here
; is that the array you're passing
; onto the function has to be
; of the same size (and type)
; as the one specified
; inside the function.
;
    Local Array[ Elements ]
;
    SetElement Array , 5 , -1
;
; Let's see if it actually works.
;
    If Array[ 5 ] = -1
        Print "It works! It works!"
    End If
;
;-------------------------------------------------------------------------------
;
; If you're a real speed demon
; you'll find that calling a lot of functions
; can slow your program down.
;
; As alternative you can use GOTOs
; which are extremely fast
; but there is another command
; which works a bit more like functions.
;
; Even though a lot of times
; you can find different ways
; to speed up your program
; without having to use GOSUBs,
; here's an example of
; exactly how they work:
;
    Local Parameter1%
    Local Parameter2#
    Local Parameter3$

    Local Return1%
    Local Return2#
    Local Return3$

    Parameter1 = 100
    Parameter2 = 1.0
    Parameter3 = "0"

    Gosub MixItUp

    Print Return1
    Print Return2
    Print Return3

    WaitKey
    End

    .MixItUp

        Return1 = Int Parameter1 + Int Parameter2 - Int Parameter3
        Return2 = Int Parameter2 + Int Parameter3 - Int Parameter1
        Return3 = Int Parameter3 + Int Parameter1 - Int Parameter2

    Return
;
; Gosub makes the program cursor
; jump to a label just like Goto,
; only you can Return to
; right after the point
; where you jumped from.
;
;   ..
;
;   Gosub MixItUp  --------------------+
;                                      |
;   Print Return1 <--------------------|-------------------------------+
;   Print Return2                      |                               |
;   Print Return3                      |                               |
;                                      |                               |
;   WaitKey                            |                               |
;   End                                |                               |
;                                      |                               |
;   .MixItUp  <------------------------+                               |
;                                                                      |
;       Return1 = Int Parameter1 + Int Parameter2 - Int Parameter3     |
;       Return2 = Int Parameter2 + Int Parameter3 - Int Parameter1     |
;       Return3 = Int Parameter3 + Int Parameter1 - Int Parameter2     |
;                                                                      |
;   Return  -----------------------------------------------------------+
;
; As you can see,
; it's a lot like a Function :)
;
;-------------------------------------------------------------------------------