;-------------------------------------------------------------------------------
;
;   ;-------------------------------;
;   ;   Variable Collections        ;
;   ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;
;
; This part is quite large, to say the least.
; So copy and paste as you see fit.
;
;-------------------------------------------------------------------------------
;
; In a lot of games you can carry multiple weapons.
; Each of these weapons would require ammunition of some sort.
; What if you wanted to create such a system?
; You could do it like this:
;
    Weapon1_Ammo = 50
    Weapon2_Ammo = 0
    Weapon3_Ammo = 0
    Weapon4_Ammo = 5
;
; There is another solution however; an array.
;
    Dim Weapon_Ammo( 4 )
;
    Weapon_Ammo( 1 ) = 50
    Weapon_Ammo( 2 ) = 0
    Weapon_Ammo( 3 ) = 0
    Weapon_Ammo( 4 ) = 5
;
; You're probably wondering why anyone wouldn't want to use
; the topmost solution - it does look a lot easier! :)
; Ofcourse it's all up to the programmer.
; But imagine having a huge amount of weapons.
; And you wanted to display the amount of ammo
; for each weapon on the screen.
; For the topmost approach:
;
    Print "Weapon 1 ammo: " + Weapon1_Ammo
    Print "Weapon 2 ammo: " + Weapon2_Ammo
    Print "Weapon 3 ammo: " + Weapon3_Ammo
    Print "Weapon 4 ammo: " + Weapon4_Ammo
    Print
    WaitKey
;
; And for the array:
;
    For Weapon_Number = 1 To 4
        Print "Weapon " + Weapon_Number + " ammo: " + Weapon_Ammo( Weapon_Number )
    Next
    Print
    WaitKey
;
; E.g. you can easily walk through each element in the array
; instead of copying, pasting and editing every line :)
;
; The For..Next loop you see up there repeats the Print statement 4 times.
; The variable Weapon_Number - which did not exist before that point -
; will be created as integer variable and a value of 1 is added to it
; with each repetition, inside the For..Next.
;
; Here's a couple of alternatives:
;
; Repeat..Until
;
    Weapon_Number = 0
    Repeat
        Weapon_Number = Weapon_Number + 1
        Print "Weapon " + Weapon_Number + " ammo: " + Weapon_Ammo( Weapon_Number )
    Until Weapon_Number = 4
    Print
    WaitKey
;
    Weapon_Number = 1
    Repeat
        Print "Weapon " + Weapon_Number + " ammo: " + Weapon_Ammo( Weapon_Number )
        Weapon_Number = Weapon_Number + 1
    Until Weapon_Number = 5
    Print
    WaitKey
;
; While..Wend
;
    Weapon_Number = 0
    While Weapon_Number < 4  ; Keep repeating until Weapon_Number >= 4
        Weapon_Number = Weapon_Number + 1
        Write "Weapon "      ; Use Write if you don't want
        Write Weapon_Number  ; the cursor to go to
        Write " ammo: "      ; the next line.
        Print Weapon_Ammo( Weapon_Number )
    Wend
    Print
    WaitKey
;
; And there are lots more!
;
;-------------------------------------------------------------------------------
;
; Remember what happens when a variable is used
; or called upon for the first time?
;
    A_New_Variable = 0
;
; It is created, declared, initialized; its type is set.
;
    Local An_Integer_Variable% = 0
;
; By default, all variables will be set to 0 when created.
; This also applies to arrays.
; So when you write
;
    Dim Weapon_Ammo( 4 )
;
; for the first time,
; a number of elements will be created and set to 0.
;
; Did you notice that each element in the array is also of a specific type?
; That's right, the Weapon_Ammo array is an array of integers!
;
    Dim Weapon_Ammo%( 4 )
;
; Another thing you see above is that you can redefine an array.
; When you do this, everything inside the array will be set to 0 again.
; And, not only can you erase an entire array, you can even change its size!
;
    Dim Weapon_Ammo( 1 )
;
; But wait - there is more :P
; When an array is created it doesn't start counting from 1.
;
    Weapon_Ammo( 0 ) = 50
    Weapon_Ammo( 1 ) = 5
;
; There are actually 2 elements in it, when you define it with ( 1 ).
; So there's an extra element ( 0 ).
; This is the difference between 0-based and 1-based orientation.
; E.g. start counting from 0 instead of 1.
; It's usually just another case of personal preference :)
;
; Let's take a look at what our Weapon_Ammo array looks like,
; schematically:
;
;   |   0   |   1   | - Element (weapon number)
;   +-------+-------+
;   |       |       |
;   |  50   |   5   | - Contents (ammo amount)
;   |       |       |
;   +-------+-------+
;   |     Array     |
;   +---------------+
;
; Resizing the array to its original size.
; All contents is lost.
;
    Dim Weapon_Ammo( 4 )
;
;   |   0   |   1   |   2   |   3   |   4   | - Element
;   +-------+-------+-------+-------+-------+
;   |       |       |       |       |       |
;   |   0   |   0   |   0   |   0   |   0   | - Contents
;   |       |       |       |       |       |
;   +-------+-------+-------+-------+-------+
;   |                 Array                 |
;   +---------------------------------------+
;
; As with normal variables,
; you can't change the type of the elements
; once an array has been declared for the first time.
; So let's take a new array, an array of strings.
; For example, if we want to store the name of each weapon.
;
    Dim Weapon_Name$( 4 )
;
    Weapon_Name( 1 ) = "Pistol"
    Weapon_Name( 2 ) = "Shotgun"
    Weapon_Name( 3 ) = "Flame thrower"
    Weapon_Name( 4 ) = "Rocket launcher"
;
; Again, as with variables, once arrays are defined,
; you can omit the type identifier ($, #, etc),
; as you can see above.
;
; You can declare arrays of any type.
; Just to recap, here are the available types:
;
;   %               Integer variable
;   #               Floating point variable
;   $               String variable
;   .[Type name]    Pointer variable (more about this soon)
;
; If you can remember, variables are used like this:
;
;   [Variable name][Variable type]
;
; Arrays are used like this:
;
;   [Array name][Type of elements]([Number of elements])
;
; Number of elements is actually the number of elements + 1, as shown before.
;
;-------------------------------------------------------------------------------
;
; Unlike normal variables, normal arrays
; - declared using the Dim keyword -
; are always global.
; So you can use them anywhere in your program.
;
; There is another trick you can do with arrays.
; When you declare an array you use the Dim keyword,
; which is short for dimension.
; Which would indicate that arrays can be multidimensional.
; Is this true?
;
    Dim Grid( 6 , 4 )
;
;      |   0   |   1   |   2   |   3   |   4   |   5   |   6   |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    0 |   0   |   0   |   0   |   0   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    1 |   0   |   0   |   0   |   0   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    2 |   0   |   0   |   0   |   0   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    3 |   0   |   0   |   0   |   0   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    4 |   0   |   0   |   0   |   0   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   +--+-------+-------+-------+-------+-------+-------+-------+
;   |                           Array                          |
;   +----------------------------------------------------------+
;
; Apparently :P
; In the above example, a 2-dimensional array, like a grid.
; Imagine a maze where you can walk through.
; So you'd want some walls.
;   - How?
; Let's say that a value of 0 (all elements currently)
; means that you can walk there.
; And a value of 1 means there's a wall there.
; You can choose any values you want ofcourse,
; it's all up to the programmer :)
;
; Let's place a wall in the center of the map (3,2).
;
    Grid( 3 , 2 ) = 1
;
; This code doesn't really convey much
; as you'll read back sometime and wonder what the 1 stands for,
; but we can do something about that :)
;
    Const Free = 0
    Const Wall = 1
;
    Grid( 3 , 2 ) = Wall
;
; You'll probably remember the 'state-of-life'.
; This is a perfect example of those state identifiers.
;
; Now let's place a larger wall section.
; So we'd have to fill a number of places on the grid with the value 1.
; You could do it like this:
;
    Grid( 0 , 0 ) = Wall
    Grid( 0 , 1 ) = Wall
    Grid( 0 , 2 ) = Wall
    Grid( 0 , 3 ) = Wall
    Grid( 0 , 4 ) = Wall
;
; So you'd get a vertical wall section on the left side of the grid.
; But you could also use a For..Next loop for that.
;
    For Y = 0 To 4
        Grid( 0 , Y ) = Wall
    Next
;
;      |   0   |   1   |   2   |   3   |   4   |   5   |   6   |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    0 |   1   |   0   |   0   |   0   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    1 |   1   |   0   |   0   |   0   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    2 |   1   |   0   |   0   |   1   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    3 |   1   |   0   |   0   |   0   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    4 |   1   |   0   |   0   |   0   |   0   |   0   |   0   |
;      |       |       |       |       |       |       |       |
;   +--+-------+-------+-------+-------+-------+-------+-------+
;   |                           Array                          |
;   +----------------------------------------------------------+
;
; Let's try the opposite side.
;
    For Y = 0 To 4
        Grid( 6 , Y ) = Wall
    Next
;
; And if you wanted to complete the box with a couple of
; horizontal wall sections, well..
; I think you'll understand the code below.
;
    For X = 0 To 6
        Grid( X , 0 ) = Wall
        Grid( X , 4 ) = Wall
    Next
;
; Yes, we're actually putting a wall in each corner for the second time.
; It doesn't really need to be fixed,
; as it won't cause bugs or slowdowns,
; but here's what we could have done:
;
    For X = 1 To 5
        Grid( X , 0 ) = Wall
        Grid( X , 4 ) = Wall
    Next
;
; Now, it may seem pretty obvious what the grid looks like.
;
;      |   0   |   1   |   2   |   3   |   4   |   5   |   6   |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    0 |   1   |   1   |   1   |   1   |   1   |   1   |   1   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    1 |   1   |   0   |   0   |   0   |   0   |   0   |   1   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    2 |   1   |   0   |   0   |   1   |   0   |   0   |   1   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    3 |   1   |   0   |   0   |   0   |   0   |   0   |   1   |
;      |       |       |       |       |       |       |       |
;   ---+-------+-------+-------+-------+-------+-------+-------+
;      |       |       |       |       |       |       |       |
;    4 |   1   |   1   |   1   |   1   |   1   |   1   |   1   |
;      |       |       |       |       |       |       |       |
;   +--+-------+-------+-------+-------+-------+-------+-------+
;   |                           Array                          |
;   +----------------------------------------------------------+
;
; But it might not be as obvious
; how to display the grid on the screen.
; (Yes, I know, it doesn't really look like a maze :P)
;
; If we were to walk through each element in our grid,
; how would we do that in code?
; It is very similar to the first For..Next loop in this program.
;
; If you remember,
; we did a couple of combined loops.
; Even an example of a checkerboard.
;
    For Y = 0 To 4
        For X = 0 To 6

            ; Grid( X , Y )

        Next
    Next
;
; And that's all there is to it! :)
; Well, okay, not all, I mean,
; we still have to put it on the screen :P
;
    For Y = 0 To 4
        For X = 0 To 6

            Write Grid( X , Y )         ; Same line.

        Next
        Print                           ; Next line.
    Next
    WaitKey
;
; Note that the X and Y dimensions can be easily mixed-up.
; This can be dangerous to your code's health :)
; So be careful how you order your dimensions.
;
; Here's an example of what might happen:
;
    Print
    For Y = 0 To 4
        For X = 0 To 4                  ; Made smaller to stay
                                        ; within grid range.
            Write Grid( Y , X )         ; Swapped X with Y.

        Next
        Print
    Next
    WaitKey
;
; The grid gets rotated 90 degrees!
; Hmm, not exactly what we had in mind :)
;
; I've made the X range smaller
; otherwise Blitz will complain
; that we're trying to access
; an element that lies beyond
; the range of our array.
;
;-------------------------------------------------------------------------------
;
; By the way, the Write and Print commands
; are not exactly graphical commands.
; These, as well as their friends Locate and Input
; are not totally satisfiable. (eh?)
; I'll explain this later.
;
; So let's try some more 'gamey' commands.
; There's some more maths required though.
;
; First, let's CLear the Screen.
;
    Cls
;
; And place some Text at a pixel location of our desire.
;
    Text 100 , 100 , "<- (100,100)"
    WaitKey
;
; Text, hmm?
; Here's the syntax:
;
;   Text (Pixel X location) , (Pixel Y location) , (Text)
;
; There are more optional parameters, (say what?)
; but I'll leave those up to you to find out :P
; Parameters, you know?
; Those thingies you put behind a command,
; separated by commas.
;
; If you're inside BlitzBasic,
; you can press F1 when the cursor is on or near a command/keyword,
; and at the bottom of the window you will see the quick help (syntax).
; Pressing F1 again will bring up the full help page.
;
; Let's try a loop with the Text command.
; A vertical display of numbers below (100,100) on screen.
;
    For Y = 1 To 5
        Text 100 , 100 + Y * 10 , Y
    Next
;
; What happens in the loop is
;
;   Y = 1   Pixel X Location = 100
;           Pixel Y Location = 100 + 1 * 10     ; 100 + 10 = 110
;           Text = 1
;
;   Y = 2   Pixel X Location = 100
;           Pixel Y Location = 100 + 2 * 10     ; 100 + 20 = 120
;           Text = 2
;
;   Y = 3   Pixel X Location = 100
;           Pixel Y Location = 100 + 3 * 10     ; 100 + 30 = 130
;           Text = 3
;
;   Y = 4   Pixel X Location = 100
;           Pixel Y Location = 100 + 4 * 10     ; 100 + 40 = 140
;           Text = 4
;
;   Y = 5   Pixel X Location = 100
;           Pixel Y Location = 100 + 5 * 10     ; 100 + 50 = 150
;           Text = 5
;
; So we leave exactly 10 pixels space for each piece of text, vertically.
;
; Let's try something more interesting.
;
    For GridY = 0 To 4
        For GridX = 0 To 6

            ScreenX = GridX * 10             ; Pixel X Location.
            ScreenY = GridY * 10             ; Pixel Y Location.
            Display = Grid( GridX , GridY )  ; Number to put on screen.

            Text ScreenX , ScreenY , Display

        Next
    Next
    WaitKey
;
;  - Isn't the result of that (almost) the same as with Write and Print?
; Indeed it is. The point is that Text has advantages over Write and Print.
;  - Which advantages?
; I guess you want to know everything, huh? :)
; First, Text is faster.
; And second, Text is more flexible.
;  - More flexible? How?
; You can center the text you want to display on a certain coordinate,
; without having to do the maths for it.
;  - How?
; Enough questions! :P
; Please read the Blitz help for more..
; Right now we need colors!
;
    Color 255 , 0 , 0   ; (eh?)
;
; That is how we can set the current drawing color.
; Syntax:
;
;   Color (Red) , (Green) , (Blue)
;
; The combined color components give you a color of your desire.
; You can specify values in the range of 0 and 255,
; where 0 means darkest and 255 means brightest.
;
; So the current drawing color is now; Red.
;
; Some more examples:
;
    Color   0 , 255 ,   0  ; Green
    Color   0 ,   0 , 255  ; Blue
    Color 255 , 255 , 255  ; White
    Color   0 ,   0 ,   0  ; Black
    Color 255 , 255 ,   0  ; Yellow
    Color 255 ,   0 , 255  ; Purple
    Color 128 , 128 , 128  ; Gray
    Color 255 , 128 ,   0  ; Orange
    Color 128 ,  64 ,   0  ; Brown
    Color  16 ,  96 , 160  ; Creme Blue
;
; So if we start putting something on the screen now,
; it will be... Creme Blue :)
;
    Text 0 , 100 , "Creme Blue"
;
; Let's take our old loop and throw in some colors.
;
    For GridY = 0 To 4
        For GridX = 0 To 6

            ScreenX = GridX * 10
            ScreenY = GridY * 10
            Display = Grid( GridX , GridY )

            If Display
                Color 0 , 128 , 255
            Else
                Color 128 , 64 , 0
            End If

            Text ScreenX , ScreenY , Display

        Next
    Next
    WaitKey
;
; If an element in our grid contains a non-zero value,
; it will be placed on the screen in Light Blue,
; otherwise Brown.
;
; We are actually overwriting our old grid display on the screen.
; That is, if you're running these couple of sections in one go.
;
; Btw, you can also apply some 'glue'
; to get rid of the extra variables.
; Like this:
;
;   Text GridX * 10 , GridY * 10 , Grid( GridX , GridY )
;
; It can be harder to read though.
;
; The screen is cleared with the color black by default.
; But you can change that.
;
    ClsColor 128 , 64 , 0
;
; The ClsColor command works the same as the Color command.
; But it applies only to the Cls command.
;
    Cls
;
; This would clear your screen with the color.. Brown :)
;
;-------------------------------------------------------------------------------
;
; We've been using a 2-dimensional array.
; So it's time for a 3-dimensional array.
;
    Dim Grid3D$( 10 , 10 , 1 )
;
; That would be.. 11 * 11 * 2 = 242 elements.
; Kinda like this:
;
;       ---+---+---+---+---+---+---+---+---+---+---+---+
;       1 /   /   /   /   /   /   /   /   /   /   /   /|
;     ---+---+---+---+---+---+---+---+---+---+---+---+ +
;     0 /   /   /   /   /   /   /   /   /   /   /   /|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    0 |   |   |   |   |   |   |   |   |   |   |   |/|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    1 |   |   |   |   |   |   |   |   |   |   |   |/|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    2 |   |   |   |   |   |   |   |   |   |   |   |/|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    3 |   |   |   |   |   |   |   |   |   |   |   |/|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    4 |   |   |   |   |   |   |   |   |   |   |   |/|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    5 |   |   |   |   |   |   |   |   |   |   |   |/|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    6 |   |   |   |   |   |   |   |   |   |   |   |/|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    7 |   |   |   |   |   |   |   |   |   |   |   |/|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    8 |   |   |   |   |   |   |   |   |   |   |   |/|/|
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + +
;    9 |   |   |   |   |   |   |   |   |   |   |   |/|/ \
;   ---+---+---+---+---+---+---+---+---+---+---+---+ + 1
;   10 |   |   |   |   |   |   |   |   |   |   |   |/ \
;   ---+---+---+---+---+---+---+---+---+---+---+---+ 0
;      | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 \
;
; Or like this:
;
;      |   0   |   1   |   2   |   3   |   4   |   5
;   ---+---+---+---+---+---+---+---+---+---+---+-- - -
;      | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
;    0 |---+---|---+---|---+---|---+---|---+---|-- - -
;      |   :   |   :   |   :   |   :   |   :   |
;   ---+-------+-------+-------+-------+-------+-- - -
;      | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
;    1 |---+---|---+---|---+---|---+---|---+---|-- - -
;      |   :   |   :   |   :   |   :   |   :   |
;   ---+-------+-------+-------+-------+-------+-- - -
;      | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
;    2 |---+---|---+---|---+---|---+---|---+---|-- - -
;      |   :   |   :   |   :   |   :   |   :   |
;   ---+-------+-------+-------+-------+-------+-- - -
;      | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
;    3 |---+---|---+---|---+---|---+---|---+---|-- - -
;      |   :   |   :   |   :   |   :   |   :   |
;   ---+-------+-------+-------+-------+-------+-- - -
;      |       |       |       |       |       |
;    4 :       :       :       :       :       :  etc
;
; So if you would say
;
;   Grid3D( 0 , 0 , 1 ) = 6
;
; here's what would happen:
;
;      |   0   |   1
;   ---+---+---+-- - -
;      | 0 | 1 |
;    0 |---+---|-- - -
;      |   : 6 |
;   ---+-------+-- - -
;      |       |
;    1 :       :  etc
;
; So now we can store a unique color for each element,
; as well as a unique character (A, z, 0, !, etc).
;
; We'd have to agree on how to store the things again.
; For example, for each element on the grid
; field 0 would contain the color and
; field 1 would contain the character.
;
; You saw I picked an array of strings so it makes
; storing both types (values and text) easier.
;
; Let's use some sort of index selector to
; distinguish color from character. (a what?)
; Just to make the code more clear.
;
    Const Grid3D_Color = 0
    Const Grid3D_Char  = 1
;
; Here's an example:
;
    Grid3D( 10 , 10 , Grid3D_Char ) = "A"
;
; Hopefully this would mean that we put a capital A
; in the lower right corner of the grid.
; But we're not there yet.
;
; Let's remove it before anyone notices it :P
;
    Grid3D( 10 , 10 , Grid3D_Char ) = ""
;
; We need to know which colors we're gonna use.
; I mean, we only have 1 field to store a color.
; We could increase the number of fields in the array,
; to be able to use 2 new fields,
; so we would have one field for Red,
; one for Green and one for Blue.
; E.g. having an array that looks like this:
;
;   Dim Grid3D$( 10 , 10 , 3 )
;
; But let's do it the hard way :P
;
; As before, we can agree on some
; constants for colors we want to use.
;
; Suppose we want simply red, green and blue.
;
    Const Color_Red   = 0
    Const Color_Green = 1
    Const Color_Blue  = 2
;
; Again, which values they contain doesn't really matter,
; so long as the values are unique.
; You could even use strings if you wanted to,
; as we're using a grid of strings.
;
; Example:
;
;   Grid3D( 5 , 5 , Grid3D_Color ) = Color_Red
;
; So this would be a 'state-of-life' again.
; Like in the previous parts.
;
; You're right, this has nothing to do with
; displaying it on the screen, yet :P
;
; By default, the grid is empty, because it's a grid of strings.
; When you store a number, it will be converted to text.
; And if want to get the number back,
; and store it in an integer variable,
; the text will be translated back into a number.
;
; You can imagine a problem when you try to convert
; text that's not a number, into a number.
;
    Value = "ABC"
;
; As said before, you cannot store text in an integer variable.
; So the text will be converted to a number.
; If the text is not a number, it will be converted to 0. (eek)
;
; So when the whole grid contains empty strings,
; you will get a grid of zeroes
; when converting each field to a number.
;
; So each color field contains Color_Red (zero)
; after converting it to a number.
; Also there's no need to convert the character field
; so now each character field contains just "" (empty).
;
; But what if we tried to compare a string with a number?
; Like we want to know what color we have stored.
; And currently all color fields contain "" (empty).
;
    Value = 0
    If Value = "" Then Print "Zero is equal to Empty"
;
; Apparently Blitz doesn't think
; zero is equal to empty.
;
; However, if you really want to,
; you can force a conversion,
; like this:
;
    ConvertedValue = ""
    If Value = ConvertedValue Then Print "Zero is equal to (converted) Empty"
;
; or like this:
;
    If Value = Int ( "" ) Then Print "Zero is equal to (converted) Empty"
;
; These are the available conversion tools:
;
;   Integer     Int ()
;   String      Str ()
;   Float       Float ()
;
; The brackets are optional.
;
    If Value = Int "" Then Print "Brackets are optional"
;
; So remember this when you're
; converting, glueing or comparing.
;
; Let's put a blue exclamation mark in the upperleft corner.
; Can you think of how to do that?
;
    Grid3D( 0 , 0 , Grid3D_Color ) = Color_Blue
    Grid3D( 0 , 0 , Grid3D_Char  ) = "!"
;
; Now let's try build a routine to display the grid.
; First, the loops.
;
    For Y = 0 To 10
        For X = 0 To 10

        Next
    Next
;
; At the end of these loops, X and Y will both equal 11.
; So I'll just reset X and Y to 0
; to prevent going off the grid
; in the code coming up.
;
    X = 0
    Y = 0
;
; We have to set the color first,
; and then draw the character.
;
; If we find Color_Red on a spot,
; we have to set.. a red color.
;
    If Grid3D( X , Y , Grid3D_Color ) = Color_Red
        Color 255 , 0 , 0
    End If
;
; If we find Color_Green in a field,
; the current drawing color must be green.
;
    If Grid3D( X , Y , Grid3D_Color ) = Color_Green
        Color 0 , 255 , 0
    End If
;
; And finally for Color_Blue, blue.
;
    If Grid3D( X , Y , Grid3D_Color ) = Color_Blue
        Color 0 , 0 , 255
    End If
;
; Ofcourse we won't find any of these
; since each color field contains "" (empty).
; As comparing a "" with any number
; won't be result in a color change.
;
; Okay, now stack them.
;
    If Grid3D( X , Y , Grid3D_Color ) = Color_Red
        Color 255 , 0 , 0
    End If
    If Grid3D( X , Y , Grid3D_Color ) = Color_Green
        Color 0 , 255 , 0
    End If
    If Grid3D( X , Y , Grid3D_Color ) = Color_Blue
        Color 0 , 0 , 255
    End If
;
; No, not like that.
;
    If Grid3D( X , Y , Grid3D_Color ) = Color_Red
        Color 255 , 0 , 0
    Else If Grid3D( X , Y , Grid3D_Color ) = Color_Green
        Color 0 , 255 , 0
    Else If Grid3D( X , Y , Grid3D_Color ) = Color_Blue
        Color 0 , 0 , 255
    End If
;
; Yeah, that's it.
;
; And maybe you recall a Select Case
; technique for doing that as well.
;
    Select Grid3D( X , Y , Grid3D_Color )
        Case Color_Red
            Color 255 , 0 , 0
        Case Color_Green
            Color 0 , 255 , 0
        Case Color_Blue
            Color 0 , 0 , 255
    End Select
;
; So which character should we display?
;
   Char$ = Grid3D( X , Y , Grid3D_Char )
;
; Oooohh.. storing it in a string variable.
; Because if we store it in an integer variable,
; it will be converted to zero if not a number!
;
; Okay, and where should we place the character?
; Hmm.. maths :)
;
; Let's use a distance of 10 pixels for each character.
; Just like before.
;
    WhereX = X * 10
    WhereY = Y * 10
;
; Maybe not in the upperleft corner of the screen,
; but somewhere more in the middle.
;
    WhereX = X * 10 + 100
    WhereY = Y * 10 + 100
;
; Text on the screen?
;
    Text WhereX , WhereY , Char
;
; Good girl.
;
; Now merge'm.
;
    For Y = 0 To 10
        For X = 0 To 10

            If Grid3D( X , Y , Grid3D_Color ) = Color_Red
                Color 255 , 0 , 0
            Else If Grid3D( X , Y , Grid3D_Color ) = Color_Green
                Color 0 , 255 , 0
            Else If Grid3D( X , Y , Grid3D_Color ) = Color_Blue
                Color 0 , 0 , 255
            End If

            Char = Grid3D( X , Y , Grid3D_Char )

            WhereX = X * 10 + 100
            WhereY = Y * 10 + 100

            Text WhereX , WhereY , grid3d(x,y,grid3d_color)

        Next
    Next
    WaitKey
;
; You should see a red liney thingy somewhere,
; which would be the red exclamation mark.
; If not, you probably didn't copy and paste enough code :)
;
; As before, you can get rid of the Char,
; WhereX and WhereY variables.
; It's all up to you :)
;
; Try playing around some more
; with the grid, colors and text.
; Practice makes perfect ;)
;
;-----------------------------------------------------------------------------------------------------------------------
;
; There's a way to easily store a tilemap in your code.
;
    .Tilemap
    Data 10 , 10    ; Dimensions

    Data Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall
    Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
    Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
    Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
    Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
    Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
    Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
    Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
    Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
    Data Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall
;
; Ofcourse you could also use ones and zeroes.
;
; Blitz will store each data element in sequential order;
; from left to right, and from top to bottom:
;
;   .Tilemap: 10 -> 10 -> Wall -> Wall -> Wall -> etc..
;
; It's a lot like the Blitz program cursor
; which reads your program from top to bottom.
;
; You can use the Restore command
; to position the data reading cursor
; at the first Data statement
; under the specified Label.
;
    Restore Tilemap
;
; By default the data reading cursor
; starts from the top of your program.
;
; You can read data elements using the Read command.
;
;   Read Value      ; Reads the next value from data.
;
; So you can first read the dimensions of the tilemap.
;
    Read Tilemap_SizeX
    Read Tilemap_SizeY
;
; Then erase and resize the tilemap
; using these new dimensions.
;
    Dim Tilemap( Tilemap_SizeX , Tilemap_SizeY )
;
; Now, if you would use a double loop
; you could read in the entire tilemap.
;
    For Y = 1 To Tilemap_SizeY
        For X = 1 To Tilemap_SizeX

            ; Read the next data element
            ; and put its value in a variable of your choice.
            Read Tilemap( X , Y )

        Next
    Next
;
; I guess you know how to display it on screen :)
;
;-----------------------------------------------------------------------------------------------------------------------
;
; Let's clear the screen and reset the colors
; so we can use some simple commands again
; to go easy on the brain :P
;
    ClsColor 0 , 0 , 0
    Cls
    Color 255 , 255 , 255
;
; To go to the next level, pointanoids,
; we need to go back to the basics.
; And replay all that has passed.
;
; An integer variable.
;
    Integer_Variable% = 1000
;
;   +---------------+
;   |               |
;   |     1000    <----
;   |               |
;   +---------------+
;   | Integer var.  |
;   +---------------+
;
; A floating point variable.
;
    FloatingPoint_Variable# = 1.000
;
;   +---------------+
;   |               |
;   |     1.0     <----
;   |               |
;   +---------------+
;   | Float var.    |
;   +---------------+
;
; A string variable.
;
    String_Variable$ = "1.000,00"
;
;     |   |   |   |   |   |   |   |
;     v   v   v   v   v   v   v   v
;   |   |   |   |   |   |   |   |   |
;   | 1 | . | 0 | 0 | 0 | , | 0 | 0 |
;   +---+---+---+---+---+---+---+---+-- -
;   | String variable
;   +------------------------------ -- -
;
; An array of integers.
;
    Const NumberOfElements% = 3
;
    Dim ArrayOfIntegers%( NumberOfElements )
;
;           |               |               |               |
;   +-----  v  -----+-----  v  -----+-----  v  -----+-----  v  -----+
;   |               |               |               |               |
;   |       0       |       0       |       0       |       0       |
;   |               |               |               |               |
;   +---------------+---------------+---------------+---------------+
;   | Integer       | Integer       | Integer       | Integer       |
;   +---------------+---------------+---------------+---------------+
;   | Array of integer variables                                    |
;   +---------------------------------------------------------------+
;
; An array of floats.
;
    Dim ArrayOfFloats#( NumberOfElements )
;
;           |               |               |               |
;   +-----  v  -----+-----  v  -----+-----  v  -----+-----  v  -----+
;   |               |               |               |               |
;   |      0.0      |      0.0      |      0.0      |      0.0      |
;   |               |               |               |               |
;   +---------------+---------------+---------------+---------------+
;   | Float         | Float         | Float         | Float         |
;   +---------------+---------------+---------------+---------------+
;   | Array of floating point variables                             |
;   +---------------------------------------------------------------+
;
; And finally, an array of strings.
;
    Dim ArrayOfStrings$( NumberOfElements )
;
;     |           |           |           |
;     v           v           v           v
;   |           |           |           |
;   |           |           |           |
;   +---+-- -   +---+-- -   +---+-- -   +---+-- -
;   | String    | String    | String    | String
;   +-----------+-----------+-----------+-----------+
;   | Array of string variables                     |
;   +-----------------------------------------------+
;
; or
;
;   +---------------+
;   |               |
;   |  String 0   <----
;   |               |
;   +---------------+
;   |               |
;   |  String 1   <----
;   |               |
;   +---------------+
;   |               |
;   |  String 2   <----
;   |               |
;   +---------------+
;   |               |
;   |  String 3   <----
;   |               |
;   +---------------+-----------+
;   | Array of string variables |
;   +---------------------------+
;
; Remember our array of colors and characters?
;
;   Dim Grid3D( X , Y , Index )
;
; You can also look at it like
; each element on the 2D grid (!)
; having multiple fields so to speak:
;
;   Color (string)
;   Character (string)
;
; So far we were using constants as:
;
;   State identifier
;
;       Const State = ..
;
;       What_Are_We_Doing = State
;       Select What_Are_We_Doing
;           Case State
;               ..
;
;   Count identifier
;
;       Const Count = ..
;
;       NumberOfApples = Count
;       Dim Array( Count )
;
;   Index identifier
;
;       Const Index = ..
;
;       Array( Index ) = Value
;
; Each element in an array
; has to be of the same type.
;
; So what if you wanted more
; different types of fields? (err)
;
; Or what if you wanted just
; a player with various attributes?
;
    Local PlayerName$
    Local PlayerSpeed#
    Local PlayerHealth%
;
; And what if you wanted to have more than one player?
;
    Local Player1_Name$
    Local Player1_Speed#
    Local Player1_Health%
    Local Player2_Name$
    Local Player2_Speed#
    Local Player2_Health%
;
; And what if you wanted to walk through
; over 100 players with a For..Next loop?
;
    Dim Player_Name$( 100 )
    Dim Player_Speed#( 100 )
    Dim Player_Health%( 100 )
;
; And what if there could be
; any number of players?
;   - You can resize an array.
; Yes, but the contents will be lost
; when you resize it.
;   - Use a second array to copy the contents.
; Okay and what if you had 5 players
; and player 3 had to go?
; How would you do that?
;   - Manually re-arrange the contents
;     of the array by using a sorting algorithm.
; Smart ass :P
;
; There's a far more easier approach
; than all of the above.
;
; Imagine a list containing any number of objects
; where each object contains anything you want.
;
; For each object you can use a mould, a template,
; a structure or a blueprint if you will.
;
; So in the case of our player:
;
    Type Player
        Field Name$
        Field Speed#
        Field Health%
    End Type
;
; This is like our design plan for one player.
;
; You can create an existing copy of this Type,
; by using the New command.
;
;    New Player          ; New (Type)
;
; The only problem is,
; we need to stick it in a variable.
; Otherwise we can't do anything with it.
; In fact, Blitz will give you an error
; if you don't to assign it to a variable.
;
; The variable we stick it in has to be
; of the same type as the thing we're creating.
; Blitz is very strict in this,
; unlike strings, integers etc.
;
; To confuse you even further,
; the variable doesn't really contain the thing,
; it just points to the thing,
; so you can modify the thing,
; as well as change its contents.
;
    Local PointerToPlayer.Player
;
; Yes, a pointer variable.
; Or to be more precise,
; a pointer to Player variable.
;
; When a pointer variable is first created,
; it actually doesn't point to anything,
; which is called Null.
;
    If PointerToPlayer = Null
        Print "Yup, nothing there"
    End If
;
; If you would create a player object,
; imagine that this is what it would look like:
;
;   +---------------+---------------+-------------------+
;   | Name (string) | Speed (float) | Health (integer)  |
;   +---------------+---------------+-------------------+
;   | Player object                                     |
;   +---------------------------------------------------+
;
; If you compare it with the other schematics
; of the single variables and arrays above,
; you'll see that the arrow is missing.
; It indicates there's no way we can use it, yet.
;
; Here's what our pointer PointerToPlayer currently looks like:
;
;                             |
;   |                         v                         |
;   +---------------------------------------------------+
;   | Player object (Null)                              |
;   +---------------------------------------------------+
;
; The arrow is there,
; but the object is not :P
; E.g. the type is set,
; but it ain't pointing to any object.
;
; So let's make it point to something that exists.
;
    PointerToPlayer = New Player      ; (Pointer).(Type) = New (Type)
;
; Yes, you don't have to include the type of a variable
; once it has been defined, remember?
; Just like with strings, floats and integers.
;
    If PointerToPlayer <> Null
        Print "Something's there!"
    End If
;
; Now that the pointer is actually pointing to something,
; we can change the contents of what it's pointing to.
; E.g. the contents of the Player object.
;
    PointerToPlayer\Name = "Dr. I.M. D'humb"
    PointerToPlayer\Speed = 5.1       ; (Pointer).(Type)\(Field) = (Value)
    PointerToPlayer\Health = 100
;
; The backslash (\) allows you to access a field.
; And you can use these fields just like
; any other variable (string, float, etc).
;
;           |               |                 |
;           v               v                 v
;   +-----     -----+-----     -----+-------     -------+
;   | Name (string) | Speed (float) | Health (integer)  |
;   +---------------+---------------+-------------------+
;   | Player object                                     |
;   +---------------------------------------------------+
;
; Well.. for the rest all you can do is..
; Delete it! :P
;
    Delete PointerToPlayer          ; Delete (Pointer).(Type)
;
; Okay, not very useful at this point,
; but you get the idea.
;
; Note that the player object was deleted, not the pointer.
; E.g. you can't delete variables :)
;
; Also, the pointer variable PointerToPlayer
; is now pointing to.. Null.. again.
;
;                             |
;   |                         v                         |
;   +---------------------------------------------------+
;   | Player object (Null)                              |
;   +---------------------------------------------------+
;
; Blitz keeps track of all objects you created.
; So you don't have to worry (too much)
; when you're not keeping track of every single object yourself.
;
;           |                   |                   |
;           v                   v                   v
;   +-----     -----+   +-----     -----+   +-----     -----+
;   | Player object |   | Player object |   | Player object |
;   +---------------+   +---------------+   +---------------+
;
; Considering that,
; can you tell me what happens
; in the code below?
;
    PointerToPlayer = New Player
    PointerToPlayer = Null
;
; In the first line
; a new Player object is created,
; and PointerToPlayer is pointing to it.
;
; In the second line
; we manually make the pointer point to
; a non-existing object (Null).
;
; But the object is still floating somewhere.
; And because Blitz keeps track of all objects
; there is a way we can find out exactly where it is.
;
; In fact, you can walk through
; an entire collection of objects,
; using a single pointer variable.
; It's a bit like walking through an array
; using a single integer variable.
;
;           |
;           v
;   +-----     -----+
;   | Player object |
;   +---------------+--+
;      | Player object |
;      +---------------+--+
;         | Player object |
;         +---------------+
;
; Also, like with arrays,
; Blitz keeps track of the order of objects.
; For example; the first time we created a player object,
; it would be the first object.
;
;   +-+-----+
;   | |     |
;   | |  1  |
;   | |     |
;   +-+-----+
;
; All objects created after it would stack up behind it.
;
;   +-+-----+       +-+-----+       +-+-----+
;   | |     |       | |     |       | |     |
;   | |  1  | ----> | |  2  | ----> | |  3  |
;   | |     |       | |     |       | |     |
;   +-+-----+       +-+-----+       +-+-----+
;
; Now, let's go fishing for our lost player object.
; We can use the First keyword to retrieve
; the first object in the list.
;
    PointerToPlayer = First Player      ; (Pointer).(Type) = First (Type)
;
;      +-+-----+
;      | |     |
;   ---->|  1  |
;      | |     |
;      +-+-----+
;
; Yes, there is also the keyword Last
; to retrieve the last object from the list.
; It works in exactly the same way.
;
; Ofcourse if there is no first or
; last object in the list,
; all you get is Null.
; E.g. the pointer will point to
; a non-existing object.
;
; Let's put this player object to (some) use.
;
    PointerToPlayer\Name = "First Player"
    PointerToPlayer\Speed = 0
    PointerToPlayer\Health = Rand ( 1 , 100 )
;
; Rand () creates random numbers
; in the range of your choice.
; So the player above will have a random amount of health
; ranging somewhere between 0 and 101. (From 1 to 100)
;
; Unfortunately the random numbers generated are not really random.
; In fact, you could say they're completely fake.
; Everytime you ask for a random number
; you get the next number in a certain pattern.
; You can control what this pattern looks like
; with a so called seed value.
;
    SeedRnd 0
;
; Here, a seed value of 0, would give you the same
; pattern every time from this point.
; So if you'd put this at the top of your program,
; you would get the same random number order every time.
; What if we wanted different random numbers every time?
;
    SeedRnd MilliSecs ()
;
; MilliSecs () will give you
; the number of milliseconds
; since Windows started.
;
; Because you won't be running the program
; on exactly the same millisecond every day,
; it will seem that the random numbers are indeed.. random :)
; E.g. the pattern will be based on the current millisecond.
;
; So now you'll get a (supposedly) fresh random pattern
; every time you run the program.
;
; Okay, allow me to create a bunch of other players
; with some added random values.
;
    For PlayerNumber = 2 To 10

        PointerToPlayer = New Player

        PointerToPlayer\Name = "Player " + PlayerNumber  ; (text-glue)

        PointerToPlayer\Speed = Rnd ( 1 , 5 )

        PointerToPlayer\Health = Rand ( 1 , 100 )

    Next
;
; Is that a typo?
; No, Rnd () works similar to Rand ().
; Rand () returns integer values (1, 2, 3, etc).
; And Rnd () returns floating point values (0.73, 1.8651, etc).
;
; You do not *have* to specify a minimum and maximum value.
; You can also do this:
;
    Random_Int  = Rand ( 10 )    ; In range of 1 and 10.
    Random_Float = Rnd ( 10 )    ; Between 0 and 10.
;
; Note that in the above cases
; Rnd () starts at 0 while Rand () starts at 1.
;
; Through all the distractions,
; do you know how many Player objects we have now?
; We still have a player called First Player.
; And we created 9 more players with unique names.
; So we have 10 Player objects.
;
; You can walk through the entire collection of objects
; using a single pointer to Player type variable.
;
;               |
;               v
;       +-----     -----+   +---------------+   +---------------+
;   - --| Player object |---| Player object |---| Player object |-- -
;       +---------------+   +---------------+   +---------------+
;
; Like mentioned before, it is actually very similar to
; looping through an array with one integer variable.
;
;             |
;             v
;       +---     ---+   +-----------+   +-----------+
;   - --|  Element  |---|  Element  |---|  Element  |-- -
;       +-----------+   +-----------+   +-----------+
;
; And it's also similar to the above loop
; where we used 1 pointer variable to create 9 objects.
;
    For PointerToPlayer = Each Player    ; For (Pointer).(Type) = Each (Type)

        Number = Number + 1
        Write Number + ": "

        Print PointerToPlayer\Name

    Next
    WaitKey
;
; You can use the Each keyword to
; walk through all objects of the same type.
;
; E.g. the PointerToPlayer variable will point
; to every object in the list.
;
; So inside the For..Next you can access
; each object, one at a time.
;
; Each next object in the list
; will be fetched for you,
; and PointerToPlayer
; will point to it.
;
; It also possible to do this manually.
; Imagine a simple For..Next loop.
;
;   For Element = 1 to 10 : Next
;
; You can also increment by hand.
;
;   Element = 1
;   Repeat
;       Element = Element + 1
;   Until Element = 11
;
; Same goes for objects.
; Automatically:
;
;   For Pointer = Each Type : Next
;
; Manually:
;
;   Pointer = First Type
;   Repeat
;       Pointer = After Pointer    ; (Pointer).(Type) = After (Pointer).(Type)
;   Until Pointer = Null
;
; The After keyword can be used to
; go to the next object in the list.
; E.g. the object behind the
; object it's currently pointing to.
;
    PointerToPlayer = First Player

    Repeat

        PointerToPlayer = After PointerToPlayer

    Until PointerToPlayer = Null
;
; If there's After, there's also Before.
; So you can do the same thing backwards.
; Let's try that with a While..Wend loop.
;
    PointerToPlayer = Last Player

    While PointerToPlayer <> Null

        PointerToPlayer = Before PointerToPlayer

    Wend
;
; Okay, what if you want to move
; objects in the list around?
;
; There is the Insert keyword to assist you.
; There are 10 players currently, right?
; So how do you place the first player (1)
; behind the last player (10)?
;
    ; Initialize variables.
    Local FirstPlayer.Player
    Local LastPlayer.Player

    ; Locate first and last objects in list.
    FirstPlayer = First Player
    LastPlayer = Last Player

    ; Place first object behind last object.
    Insert FirstPlayer After LastPlayer
;
; It's almost real english :)
; Let's test what our first object is,
; just to be sure.
;
    FirstPlayer = First Player
    Print
    Print "First object name: " + FirstPlayer\Name
;
; Which should give you the name of Player 2 :)
;
; However, you don't always have to assign
; a variable to use an object.
; Sometimes you can combine keywords
; like there's no tomorrow.
;
    Insert Last Player Before First Player
;
; Do you know what we just did?
; That's right, we moved player named First Player
; back to its original spot.
;
; You can use Insert also, for example,
; to arrange objects in a certain order.
;
; But you don't always have to rely on
; the keywords First, Last, Before, After etc.
; Pointers will be pointers.
; You can use them in any way you want.
;
;-----------------------------------------------------------------------------------------------------------------------
;
; There are some common cases
; where you'll want to administer
; all your objects by hand.
;
; Imagine a game with players shooting at enemies.
; And enemies shooting at players.
;
; So you'd need players (just like before).
;
;   Type Player
;       Field Located_Where
;       Field Doing_What
;   End Type
;
; As well as enemies.
;
;   Type Enemy
;       Field Located_Where
;       Field Doing_What
;   End Type
;
; Now, they can shoot,
; so we'd need to store bullets.
;
;   Type Bullet
;       Field Located_Where
;   End Type
;
; All looking good
; but what if players' shots
; would hurt only enemies
; and vise versa?
;
; So you'd have to know
; who's the owner of a bullet.
; A player, or an enemy.
;
; One way is forgetting
; the old Bullet type structure
; and just using 2 separate ones.
; One for each group (players and enemies).
;
;   Type Player_Bullet
;       Field Located_Where
;   End Type
;
;   Type Enemy_Bullet
;       Field Located_Where
;   End Type
;
; Still looking good
; but it's not so funny
; when there's different types of
; players, enemies and bullets.
;
; So we add a field
; to our original Bullet type
; to know who the owner is
; e.g. which group the bullet belongs to.
;
;   Const Bullet_Of_Player = 1
;   Const Bullet_Of_Enemy  = 2
;
;   Type Bullet
;       Field Of_Whom           ; <---
;       Field Located_Where
;   End Type
;
; Now what if there are thousands of bullets
; and you don't want to loop through all bullets every time
; and still use just one type of bullet.
;
; You can't do this if you rely on Blitz' keywords.
; This may not be something that happens in your game.
; And most (simple) games will only need Blitz' keywords.
; Remember that pointers will be pointers.
; You can use them in any way you want.
;
; So, here's another solution:
;
;   Type Bullet
;       Field Located_Where
;   End Type
;
;   Type Player
;       Field Located_Where
;       Field Doing_What
;       Field FirstBullet.Bullet    ; <---
;   End Type
;
;   Type Enemy
;       Field Located_Where
;       Field Doing_What
;       Field FirstBullet.Bullet    ; <---
;   End Type
;
;-----------------------------------------------------------------------------------------------------------------------
;
; So far we've seen simple variable types as a field
; but you can also place a pointer variable in there.
;
    Type Link
        Field PointerToNextLink.Link
    End Type
;
; Now we can make our own chain of links.
;
    FirstLink.Link = New Link
;
;   FirstLink
;       |
;       v
;     ,---.
;    /     \
;   (
;    \     /
;     `---'
;
    AnotherLink.Link = New Link
;
;   FirstLink
;       |     AnotherLink
;       v          |
;     ,---.        v
;    /     \    _.---._
;   (          (
;    \     /    `^---^^
;     `---'
;
    FirstLink\PointerToNextLink = AnotherLink
;
;   FirstLink
;       | AnotherLink
;       v    |
;     ,---.  v
;    /    _>---._
;   (    (  )
;    \    ^>---^^
;     `---'
;
    AnotherLink = Null
;
;   FirstLink
;       |
;       v
;     ,---.
;    /    _>---._
;   (    (  )
;    \    ^>---^^
;     `---'
;
; So long as you keep track of the root
; or your own first link of the chain,
; you will be able to find any link in the chain
; without having to use any of the keywords.
;
; How?
;
    AnotherLink = FirstLink\PointerToNextLink
;
; Actually the reversed of what we did before.
; And you can make it really hairy if you wanted to.
;
;   FirstLink\PointerToNextLink\PointerToNextLink\PointerToNextLink\ etc..
;
; Let's add another link to the chain,
; using the same pointer variable.
;
    AnotherLink = New Link
;
;   FirstLink      AnotherLink
;       |               |
;       v               v
;     ,---.           ,---.
;    /    _>---._    /     \
;   (    (  )       (
;    \    ^>---^^    \     /
;     `---'           `---'
;
    FirstLink\PointerToNextLink\PointerToNextLink = AnotherLink
;
;  FirstLink  AnotherLink
;       |         |
;       v         v
;     ,---.     ,---.
;    /    _>---<_    \
;   (    (  ) (  )
;    \    ^>---<^    /
;     `---'     `---'
;
    AnotherLink = Null
;
;   FirstLink
;       |
;       v
;     ,---.     ,---.
;    /    _>---<_    \
;   (    (  ) (  )
;    \    ^>---<^    /
;     `---'     `---'
;
; You'll probably want to iterate
; through the manual list easily.
; E.g. walk through each object in
; our home made list, one at a time.
;
; So here's an example While..Wend loop to
; demonstrate how you can walk through
; all links in the chain.
;
    ; This will be our iterator.
    Local PointerToLink.Link

    ; Find our first link.
    PointerToLink = FirstLink

    While PointerToLink = Null

        ; Point to next link in chain.
        PointerToLink = PointerToLink\PointerToNextLink

    Wend
;
; You could add another pointer variable
; to point to the object before the current object
; to make searching through the list faster.
;
; Ofcourse this chain of links contains only a pointer variable
; so there's no real use for this chain of links
; as we can't really put some useful information in each link.
;
;-----------------------------------------------------------------------------------------------------------------------
;
; So let's put a manual linked list to good use
; and add at least one useful field.
;
    Type Element
        Field pNext.Element
        Field iValue%
    End Type
;
; Another idea is to use one (or more) letter
; of the variable name to know what type it is.
; Some examples:
;
;   iValue      ; Integer
;   sName       ; String
;   fSpeed      ; Float
;   pNext       ; Pointer
;
; Now create a random bunch of objects,
; put some random stuff in them
; and rack'em up (link the chain).
;
    ; Initialize variables.
    Local iElementCount%
    Local iElement%
    Local pRoot.Element
    Local pNext.Element

    ; Create a root element.
    pRoot = New Element
    pRoot\iValue = Rand ( 100 )

    ; Place elements behind it.
    pNext = pRoot
    iElementCount = Rand ( 10 , 20 )
    For iElement = 1 To iElementCount
        pNext\pNext = New Element
        pNext\pNext\iValue = Rand ( 100 )
        pNext = pNext\pNext
    Next
;
; Let's see what we generated.
;
    iElement = 0
    pNext = pRoot
    While pNext <> Null
        iElement = iElement + 1
        Print iElement + ": " + pNext\iValue
        pNext = pNext\pNext
    Wend
    Print
    WaitKey
;
;-----------------------------------------------------------------------------------------------------------------------
;
; There's one more type of field you can use.
;
    Type Inventory
        Field Slots[ 10 ]
    End Type
;
; It's called a BlitzArray[tm].
; And it works similar to regular arrays.
;
    Inv.Inventory = New Inventory
    Inv\Slots[ 0 ] = 293           ; (Pointer).(Type)\Array[ Element ] = Value
;
; The major difference is that
; you cannot redimension it
; e.g. you can't change its size
; or instantly free its contents
; so its size has to be constant.
;
    Const Amount = 100
;
    Type Ship
        Field Weapons[ Amount ]
        Field Engine
        Field Generator
        Field Hull
        Field Shield
    End Type
;
; If you remember normal arrays
; you'll know that we actually created
; an array of integers.
;
; And if I told you that you can use
; any type of field as a regular variable,
; would that also mean you can create
; a BlitzArray[tm] as a regular variable?
;
    Local Weapons[ Amount ]
;
; Yes! :)
;
    Global Inventory$[ 10 ]
;
; A (global) BlitzArray[tm] of strings.
;
    Inventory[ 1 ] = "Gold coin"
;
; Ofcourse BlitzArrays[tm] are most useful
; in scenarios where the size of the array
; remains constant throughout the game.
;
; Otherwise regular arrays will be an excellent choice.
; Even though regular arrays are always Global.
;
;-----------------------------------------------------------------------------------------------------------------------
;
; So you can have arrays of certain types;
; string, float and integer.
; But what about pointers?
;
    Type Thing
        Field Contents
    End Type
;
    Dim PointerArray.Thing( 0 )     ; Dim Array.Type( Elements )
;
; Look!
; An array of pointers!
; Do you see that it looks just like
; an array of a different type?
;
    Dim StringArray$( 0 )
;
; Let's do something with the first element.
;
    PointerArray( 0 ) = New Thing
    PointerArray( 0 )\Contents = 2004   ; Array.Type( Element )\Field = Value
;
; Remember what happens when we redimension the array?
; Its contents gets erased.
;
    Dim PointerArray( 1 )   ; Contains 2 elements.
;
; But what we have here is an array of pointers.
; So the actual objects were not erased.
;
; If you remember the First keyword
; you'll know how to retrieve the first object.
;
    PointerArray( 0 ) = First Thing
;
; So when we display the contents
; it should be 2004, right?
;
    Print PointerArray( 0 )\Contents
    WaitKey
;
; What about BlitzArrays[tm]?
;
    Const Alot = 10000
;
    Local BlitzArray_WithPointers.Thing[ Alot ]
;
    BlitzArray_WithPointers[ 9999 ] = PointerArray( 0 )
;
; See how you can combine everything with everything?
; Mix and blend as you see fit :)
;
;-----------------------------------------------------------------------------------------------------------------------
;
; Sometimes that can become difficult though.
; Even though Blitz is a very intelligent language,
; it won't always know what you're talking about :P
;
; You'll remember text glue,
;
    Print "Where " + "Am " + "I ?"
;
; and how to convert text to a value.
;
    TextValue$ = "5000"

    ; Auto
    Value = TextValue

    ; Manual
    Value = Int ( TextValue )
;
; Sometimes you can't rely on automatic
; conversion because Blitz won't understand
; your mysterious ways.
;
    Print "-Glue-"
;
    Print Value1 + Value2
;               /|\
;                |
;           Number glue
;
    Print Value1 + "" + Value2
;               /|\  /|\
;                |    |
;              Text glue
;
    Print Str ( Value1 ) + Str ( Value2 )
;                       /|\
;                        |
;                    Text glue
;
; And floats with integers.
;
    Print "-Conversion-"
;
    ; Just integers, not accurate.
    Value = 10 / 3 * 10
    Print Value
;
    ; Converted to float, accurate.
    Value = Float 10 / 3 * 10
    Print Value
;
    ; Using a float instead of integer, accurate.
    Value = 10.0 / 3 * 10
    Print Value
;
    ; Changed priority, accurate.
    Value = 10 * 10 / 3
    Print Value
;
; Actually, you can do the same with pointers.
;
    Type Any
        Field Thing#
    End Type
;
    pAny.Any = New Any
    pAny\Thing = -3.14
;
; There's the Handle keyword to convert to a number.
;
    Value = Handle pAny     ; hType = Handle ( Pointer.Type )
    Print Value
;
; Technically what you'll get
; is a unique memory address
; for the pointer.
;
; This way you can keep track
; of pointers by storing their address
; instead of just pointers.
;
; The Object keyword converts
; the address back to a pointer.
;
    pAny = Object.Any Value     ; Pointer.Type = Object.Type ( hType )
;
; I've used hType to indicate
; it's a handle (address, number, value)
; of a pointer of this type.
;
; And pAny would mean
; a pointer to an object of type Any.
; But you probably already knew that :)
;
; You can also use this approach
; to test any number against any type.
;
; So you could for example store
; *different* types of objects
; in a regular array of integers.
;
;   Write "It's a"
;        If Object.Engine    Array( Element ) <> Null
;     Print "n engine."
;   Else If Object.Generator Array( Element ) <> Null
;     Print " generator."
;   Else If Object.Weapon    Array( Element ) <> Null
;     Print " weapon."
;   Else If Object.Shield    Array( Element ) <> Null
;     Print " shield."
;    End If
;
; Handle and Object work exactly
; the same as Int, Str and Float.
;
;-----------------------------------------------------------------------------------------------------------------------