' ################################################################################################################################################################
' Isomatric mapping demo re-revisited
' Version 2.69 by madscijr
 
' Based on Isometric Mapping Demo
' by SMcNeill, bplus, and others at
' https://www.qb64.org/forum/index.php?topic=1903.30
 
' This crude version uses a 3-dimensional array (32x32x32)
' to store cubes of different colors,
' and draws them to the screen in 2.5D "isometric".
' Added code to render cubes that block the view of
' the player as transparent. Added a 2-D top down "map"
' view of the player's current Z slice.
 
' TO DO:
' * allow player to rotate their view
' * option to hide objects out of player's line-of-sight
' * add objects (water, ladders, ropes, windows, doors, ramps, etc.)
' * shrink grid size to 8x8 (may need to use some other rendering method)
' * expand world to bigger than screen (2.5d scrolling view)
' * show player as a stick figure (like "Realm of Impossibility")
' * add ability to walk up ramps / climb ladders / etc.
' * simultaneously show additional 1st person view
' * add ability for tilting head up/down in first person
' * split screen (x2 or x4) local multi-player version
' * make simple open world (players can add/remove blocks, build in real time, save screens)
' * make simple games (maze craze, capture the flag, snake, surround, 2.5d pong)
' * make more complex games (berzerk, lode runner, atari combat / tank)
' * make awesome complex games (2.5d lunar lander, atari adventure, asteroids, gravitar, etc.)
 
' ################################################################################################################################################################
 
' =============================================================================
' GLOBAL DECLARATIONS a$=string, i%=integer, L&=long, s!=single, d#=double
' div: int1% = num1% \ den1%
' mod: rem1% = num1% MOD den1%
 
' -----------------------------------------------------------------------------
' boolean constants
' -----------------------------------------------------------------------------
 
' -----------------------------------------------------------------------------
' KeyDownConstants
' -----------------------------------------------------------------------------
Const c_iKeyDown_Esc 
= 27 Const c_iKeyDown_F1 
= 15104 Const c_iKeyDown_F2 
= 15360 Const c_iKeyDown_F3 
= 15616 Const c_iKeyDown_F4 
= 15872 Const c_iKeyDown_F5 
= 16128 Const c_iKeyDown_F6 
= 16384 Const c_iKeyDown_F7 
= 16640 Const c_iKeyDown_F8 
= 16896 Const c_iKeyDown_F9 
= 17152 Const c_iKeyDown_F10 
= 17408 Const c_iKeyDown_Tilde 
= 96 Const c_iKeyDown_Minus 
= 45 Const c_iKeyDown_EqualPlus 
= 61 Const c_iKeyDown_BkSp 
= 8 Const c_iKeyDown_Ins 
= 20992 Const c_iKeyDown_Home 
= 18176 Const c_iKeyDown_PgUp 
= 18688 Const c_iKeyDown_Del 
= 21248 Const c_iKeyDown_End 
= 20224 Const c_iKeyDown_PgDn 
= 20736 Const c_iKeyDown_KEYPAD_7_Home 
= 18176 Const c_iKeyDown_KEYPAD_8_Up 
= 18432 Const c_iKeyDown_KEYPAD_9_PgUp 
= 18688 Const c_iKeyDown_KEYPAD_4_Left 
= 19200 Const c_iKeyDown_KEYPAD_6_Right 
= 19712 Const c_iKeyDown_KEYPAD_1_End 
= 20224 Const c_iKeyDown_KEYPAD_2_Down 
= 20480 Const c_iKeyDown_KEYPAD_3_PgDn 
= 20736 Const c_iKeyDown_KEYPAD_0_Ins 
= 20992 Const c_iKeyDown_KEYPAD_Period_Del 
= 21248 Const c_iKeyDown_Pipe 
= 105 Const c_iKeyDown_BracketLeft 
= 91 Const c_iKeyDown_BracketRight 
= 93 Const c_iKeyDown_Backslash 
= 92 Const c_iKeyDown_SemiColon 
= 59 Const c_iKeyDown_Apostrophe 
= 39 Const c_iKeyDown_Enter 
= 13 Const c_iKeyDown_Comma 
= 44 Const c_iKeyDown_Period 
= 46 Const c_iKeyDown_Slash 
= 47 Const c_iKeyDown_Up 
= 18432 Const c_iKeyDown_Left 
= 19200 Const c_iKeyDown_Down 
= 20480 Const c_iKeyDown_Right 
= 19712 Const c_iKeyDown_Spacebar 
= 32  
' -----------------------------------------------------------------------------
' constants for map (MapBlockType.Typ)
' -----------------------------------------------------------------------------
Const c_iMapType_Empty 
= 0 Const c_iMapType_Floor_Tiled 
= 1 Const c_iMapType_Wall 
= 2 Const c_iMapType_Water 
= 3 Const c_iMapType_Window 
= 4 Const c_iMapType_Player1 
= 5 Const c_iMapType_Player2 
= 6  
' -----------------------------------------------------------------------------
' constants for 2.5D movement
' -----------------------------------------------------------------------------
 
' -----------------------------------------------------------------------------
' constants for drawing the 2.5D screen
' -----------------------------------------------------------------------------
Const cScreenOffsetX 
= 500 ' 450 Const cScreenOffsetY 
= 300 ' 50  
' =============================================================================
' USER DEFINED TYPES
' =============================================================================
    Typ 
As Integer ' c_iMapType_Empty, c_iMap_Floor_Tiled, c_iMap_Wall, etc.    'Vis As Integer ' TRUE = visible, FALSE = don't render
    'Lit As Long ' light offset
    Color2 
As Long ' secondary color if needed    Color3 
As Long ' third color if needed    AlphaOverride 
As Integer ' can be used to override alpha (0 treated as opaque) 
' =============================================================================
' GLOBAL VARIABLES
 
' =============================================================================
' LOCAL VARIABLES
 
' ****************************************************************************************************************************************************************
' ACTIVATE DEBUGGING WINDOW
_Echo "Started " + m_ProgramName$
 ' ****************************************************************************************************************************************************************
 
' =============================================================================
' START THE MAIN ROUTINE
main
 
' =============================================================================
' FINISH
System ' return control to the operating system Print m_ProgramName$ 
+ " finished." Input "Press <ENTER> to continue", in$
  
' ****************************************************************************************************************************************************************
' DEACTIVATE DEBUGGING WINDOW
' ****************************************************************************************************************************************************************
 
 
' /////////////////////////////////////////////////////////////////////////////
 
    
 
        Print "Isomatric Mapping Demo Re-visited"         Print "v2.69, by Softintheheadware (Dec, 2021)"         'PRINT "CONTROLS: PRESS <ESC> TO RETURN TO MENU"
        'PRINT "PLAYER  LEFT       RIGHT       UP        DOWN       "
        'PRINT "1       CRSR LEFT  CRSR RIGHT  CRSR UP   CRSR DOWN  "
        'PRINT "2       KEYPAD 4   KEYPAD 6    KEYPAD 8  KEYPAD 2   "
        'PRINT "3       A          S           W         Z          "
        'PRINT "4       J          K           I         M          "
        'PRINT
 
        Print "1. IsometricDemo1"         Print "2. IsometricDemo2"         Print "3. Move around in 2.5D"         Print "What to do? ('q' to exit)"  
 
            result$ = IsometricDemo1
            result$ = IsometricDemo2
            result$ = IsometricDemo3
        
        
 
' /////////////////////////////////////////////////////////////////////////////
 
    Dim RoutineName 
As String: RoutineName 
= "IsometricDemo1"     Dim arrMap
(m_iMapMinX 
To m_iMapMaxX
, m_iMapMinY 
To m_iMapMaxY
, m_iMapMinZ 
To m_iMapMaxZ
) As MapBlockType
     
    ' INITIALIZE
    'Screen _NewImage(1024, 720, 32) : _ScreenMove _Middle
    
    ' =============================================================================
    ' MAIN LOOP
    bQuit = FALSE
 
        ' -----------------------------------------------------------------------------
        ' INITIALIZE MAP TO EMPTY
        ClearIsometricMap arrMap()
        
        ' -----------------------------------------------------------------------------
        ' DRAW FLOOR
        iZ% = 0
                arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iMapType_Floor_Tiled
                arrMap(iLoopX%, iLoopY%, iZ%).Color1 = cGray&
                arrMap(iLoopX%, iLoopY%, iZ%).Color2 = cLightGray&
        
        ' -----------------------------------------------------------------------------
        ' DRAW BLOCKS TO CHECK ORIENTATION
        
        For iLoopZ% 
= m_iMapMinZ 
+ 1 To m_iMapMaxZ
             arrMap(m_iMapMinX, m_iMapMinY, iLoopZ%).Typ = c_iMapType_Wall
            arrMap(m_iMapMinX, m_iMapMinY, iLoopZ%).Color1 = cRed&
            
            arrMap(m_iMapMaxX, m_iMapMinY, iLoopZ%).Typ = c_iMapType_Wall
            arrMap(m_iMapMaxX, m_iMapMinY, iLoopZ%).Color1 = cBlue&
            
            arrMap(m_iMapMinX, m_iMapMaxY, iLoopZ%).Typ = c_iMapType_Wall
            arrMap(m_iMapMinX, m_iMapMaxY, iLoopZ%).Color1 = cGreen&
            
            'arrMap(m_iMapMaxX, m_iMapMaxY, iLoopZ%).Typ = c_iMapType_Wall
            'arrMap(m_iMapMaxX, m_iMapMaxY, iLoopZ%).Color1 = cYellow&
            
            'arrMap(m_iMapMinX, m_iMapMidY, iLoopZ%).Typ = c_iMapType_Wall
            'arrMap(m_iMapMinX, m_iMapMidY, iLoopZ%).Color1 = cOrange&
            '
            'arrMap(m_iMapMaxX, m_iMapMidY, iLoopZ%).Typ = c_iMapType_Wall
            'arrMap(m_iMapMaxX, m_iMapMidY, iLoopZ%).Color1 = cPurple&
            '
            'arrMap(m_iMapMidX, m_iMapMinY, iLoopZ%).Typ = c_iMapType_Wall
            'arrMap(m_iMapMidX, m_iMapMinY, iLoopZ%).Color1 = cLime&
            '
            'arrMap(m_iMapMidX, m_iMapMaxY, iLoopZ%).Typ = c_iMapType_Wall
            'arrMap(m_iMapMidX, m_iMapMaxY, iLoopZ%).Color1 = cCyan&
        
        ' -----------------------------------------------------------------------------
        ' DRAW SOME OBJECTS
            iX% = 16
            iY% = 3
            
            iNextColor& = cRed&
            iLoopZ% = 1
            iLoopY% = iY%
            For iLoopX% 
= iX% 
To (iX% 
+ 10)                 arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iMapType_Wall
                arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1 = iNextColor&
            
            iNextColor& = cBlue&
            iLoopZ% = 1
            iLoopY% = iY% + 8
            For iLoopX% 
= iX% 
To (iX% 
+ 10)                 arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iMapType_Wall
                arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1 = iNextColor&
            
            iNextColor& = cGreen&
            iLoopZ% = 1
            iLoopX% = iX% + 1
            For iLoopY% 
= (iY% 
+ 1) To (iY% 
+ 7)                 arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iMapType_Wall
                arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1 = iNextColor&
            
            iNextColor& = cYellow&
            iLoopZ% = 1
            iLoopX% = iX% + 9
            For iLoopY% 
= (iY% 
+ 1) To (iY% 
+ 7)                 arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iMapType_Wall
                arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1 = iNextColor&
        
        ' -----------------------------------------------------------------------------
        ' DRAW A PYRAMID
            iX% = 2
            iY% = 18
            iZ% = 1
            iPosX1% = iX%
            iPosX2% = iX% + 10
            iPosY1% = iY%
            iPosY2% = iY% + 10
            iNextColor& = cRed&
            iColorScheme% = 1 ' 1 = Rainbow6 #1, 9 = Rainbow6 #2, etc.
            
            bContinue = TRUE
                ' PLOT NEXT LEVEL
                For iLoopX% 
= iPosX1% 
To iPosX2%
                     For iLoopY% 
= iPosY1% 
To iPosY2%
                         arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iMapType_Wall
                        arrMap(iLoopX%, iLoopY%, iZ%).Color1 = iNextColor&
                
                ' MOVE UP A LEVEL
                iPosX1% = iPosX1% + 1
                iPosX2% = iPosX2% - 1
                iPosY1% = iPosY1% + 1
                iPosY2% = iPosY2% - 1
                DoCycleColor iColorScheme%, iNextColor&
                
                ' QUIT AFTER WE REACH THE TOP
                If (iPosX1% 
<= iPosX2%
) And (iPosY1% 
<= iPosY2%
) Then                     iZ% = iZ% + 1
                    bContinue = FALSE
                
 
        ' -----------------------------------------------------------------------------
        ' DRAW PIPES
            ' START POSITION
            iX% = m_iMapMaxX ' 30 ' RandomNumber(0, 32)
            iY% = m_iMapMaxY ' 28 ' RandomNumber(0, 32)
            iZ% = 1 ' 32
            
            ' LENGTH OF PIPES
            iSegmentLength% = 4
            iMaxLength% = 64
            
            ' START COLOR + DEFINE HOW COLOR CHANGES
            iNextColor& = cRed&
            iColorScheme% = 2 ' 0 = don't change, 2 = Rainbow18 #1, 10 = Rainbow18 #2, etc.
            
            ' INITIALIZE
            bFirst = TRUE
            iCount% = 0
            iMove% = 0
            bFinished = FALSE
                iNextX% = iX%
                iNextY% = iY%
                iNextZ% = iZ%
                
                ' CHANGE DIRECTION EVERY iSegmentLength% SPACES
                iMove% = iMove% + 1
                If iMove% 
> iSegmentLength% 
Then                     iMove% = 0
                    
                    ' PICK A DIRECTION
                        ' MOVE UP FOR FIRST MOVE
                        iDirection% = c_iDir_Up
                        bFirst = FALSE
                        ' PICK A RANDOM DIRECTION
                        iDirection% = RandomNumber(c_iDir_Min, c_iDir_Max)
                
                            iNextZ% = iNextZ% - 1
                            iNextZ% = iNextZ% + 1
                            iNextX% = iNextX% - 1
                            iNextX% = iNextX% + 1
                            iNextY% = iNextY% - 1
                            iNextY% = iNextY% + 1
                
                ' CHECK IF NEXT SPACE IS EMPTY
                If arrMap
(iNextX%
, iNextY%
, iNextZ%
).Typ 
= c_iMapType_Empty 
Then                     ' SPACE IS EMPTY
                    ' DRAW HERE
                    
                    iCount% = iCount% + 1
                    iX% = iNextX%
                    iY% = iNextY%
                    iZ% = iNextZ%
                    
                    ' GET NEXT COLOR AND DRAW BLOCK
                    DoCycleColor iColorScheme%, iNextColor&
                    arrMap(iX%, iY%, iZ%).Typ = c_iMapType_Wall
                    arrMap(iX%, iY%, iZ%).Color1 = iNextColor&
                    
                    ' HAVE WE PLACED MAX # OF BLOCKS?
                        bFinished = TRUE
                    ' SPACE IS OCCUPIED
                    ' SEE IF WE HAVE ANY OPEN SPACES TO MOVE TO
                    iOpen% = 0
                        If arrMap
(iX%
, iY%
, iZ% 
- 1).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX%
, iY%
, iZ% 
+ 1).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX% 
- 1, iY%
, iZ%
).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX% 
+ 1, iY%
, iZ%
).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX%
, iY% 
- 1, iZ%
).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX%
, iY% 
+ 1, iZ%
).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                    
                    ' QUIT IF NO OPEN SPACES AVAILABLE
                        ' NOWHERE TO GO, EXIT
                        bFinished = TRUE
                
 
        ' PLOT GRAPHICS TO SCREEN
        DrawIsometricScreen arrMap()
        
        Input "Type q to quit? ", in$
         
            bQuit = TRUE
        
    
    
    IsometricDemo1 = sResult
 
' /////////////////////////////////////////////////////////////////////////////
 
    Dim RoutineName 
As String: RoutineName 
= "IsometricDemo2"     Dim arrMap
(m_iMapMinX 
To m_iMapMaxX
, m_iMapMinY 
To m_iMapMaxY
, m_iMapMinZ 
To m_iMapMaxZ
) As MapBlockType
     
    ' INITIALIZE
    'Screen _NewImage(1024, 720, 32) : _ScreenMove _Middle
    
    ' =============================================================================
    ' MAIN LOOP
    bQuit = FALSE
 
        ' -----------------------------------------------------------------------------
        ' INITIALIZE MAP TO EMPTY
        ClearIsometricMap arrMap()
        
        ' -----------------------------------------------------------------------------
        ' DRAW FLOOR
        'For iLoopZ% = m_iMapMinZ To m_iMapMaxZ Step 8
        For iLoopZ% 
= m_iMapMinZ 
To m_iMapMinZ
             For iLoopX% 
= m_iMapMinX 
To m_iMapMaxX
                 For iLoopY% 
= m_iMapMinY 
To m_iMapMaxY
                     arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iMapType_Floor_Tiled
                    arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1 = cGray&
                    arrMap(iLoopX%, iLoopY%, iLoopZ%).Color2 = cLightGray&
        
        ' -----------------------------------------------------------------------------
        ' DRAW FRAME AROUND ENTIRE SPACE
        
        For iLoopZ% 
= m_iMapMinZ 
+ 1 To m_iMapMaxZ
             arrMap(m_iMapMinX, m_iMapMinY, iLoopZ%).Typ = c_iMapType_Wall
            arrMap(m_iMapMinX, m_iMapMinY, iLoopZ%).Color1 = cRed&
            
            arrMap(m_iMapMaxX, m_iMapMinY, iLoopZ%).Typ = c_iMapType_Wall
            arrMap(m_iMapMaxX, m_iMapMinY, iLoopZ%).Color1 = cBlue&
            
            arrMap(m_iMapMinX, m_iMapMaxY, iLoopZ%).Typ = c_iMapType_Wall
            arrMap(m_iMapMinX, m_iMapMaxY, iLoopZ%).Color1 = cGreen&
            
            arrMap(m_iMapMaxX, m_iMapMaxY, iLoopZ%).Typ = c_iMapType_Wall
            arrMap(m_iMapMaxX, m_iMapMaxY, iLoopZ%).Color1 = cYellow&
        
        For iLoopX% 
= m_iMapMinX 
To m_iMapMaxX
             arrMap(iLoopX%, m_iMapMinY, m_iMapMinZ + 1).Typ = c_iMapType_Wall
            arrMap(iLoopX%, m_iMapMinY, m_iMapMinZ + 1).Color1 = cOrange&
            
            arrMap(iLoopX%, m_iMapMaxY, m_iMapMaxZ).Typ = c_iMapType_Wall
            arrMap(iLoopX%, m_iMapMaxY, m_iMapMaxZ).Color1 = cPurple&
            
            arrMap(iLoopX%, m_iMapMaxY, m_iMapMinZ + 1).Typ = c_iMapType_Wall
            arrMap(iLoopX%, m_iMapMaxY, m_iMapMinZ + 1).Color1 = cLime&
            
            arrMap(iLoopX%, m_iMapMinY, m_iMapMaxZ).Typ = c_iMapType_Wall
            arrMap(iLoopX%, m_iMapMinY, m_iMapMaxZ).Color1 = cCyan&
        
        For iLoopY% 
= m_iMapMinY 
To m_iMapMaxY
             arrMap(m_iMapMinX, iLoopY%, m_iMapMinZ + 1).Typ = c_iMapType_Wall
            arrMap(m_iMapMinX, iLoopY%, m_iMapMinZ + 1).Color1 = cDodgerBlue&
            
            arrMap(m_iMapMinX, iLoopY%, m_iMapMaxZ).Typ = c_iMapType_Wall
            arrMap(m_iMapMinX, iLoopY%, m_iMapMaxZ).Color1 = cDeepPurple&
            
            arrMap(m_iMapMaxX, iLoopY%, m_iMapMinZ + 1).Typ = c_iMapType_Wall
            arrMap(m_iMapMaxX, iLoopY%, m_iMapMinZ + 1).Color1 = cDarkRed&
            
            arrMap(m_iMapMaxX, iLoopY%, m_iMapMaxZ).Typ = c_iMapType_Wall
            arrMap(m_iMapMaxX, iLoopY%, m_iMapMaxZ).Color1 = cGold&
        
        ' -----------------------------------------------------------------------------
        ' DRAW PIPES
            ' START POSITION
            iX% = m_iMapMidX ' 30 ' RandomNumber(0, 32)
            iY% = m_iMapMidY ' 28 ' RandomNumber(0, 32)
            iZ% = m_iMapMidZ ' 1 ' 32
            
            ' LENGTH OF PIPES
            iSegmentLength% = 8
            iMaxLength% = 512
            
            ' START COLOR + DEFINE HOW COLOR CHANGES
            iNextColor& = cRed&
            iColorScheme% = 3 ' 0 = don't change, 2 = Rainbow18 #1, 10 = Rainbow18 #2, etc.
            
            ' INITIALIZE
            bFirst = TRUE
            iCount% = 0
            iMove% = 0
            bFinished = FALSE
                iNextX% = iX%
                iNextY% = iY%
                iNextZ% = iZ%
                
                ' CHANGE DIRECTION EVERY iSegmentLength% SPACES
                iMove% = iMove% + 1
                If iMove% 
> iSegmentLength% 
Then                     iMove% = 0
                    
                    ' PICK A DIRECTION
                        ' MOVE UP FOR FIRST MOVE
                        iDirection% = c_iDir_Up
                        bFirst = FALSE
                        ' PICK A RANDOM DIRECTION
                        iDirection% = RandomNumber(c_iDir_Min, c_iDir_Max)
                
                            iNextZ% = iNextZ% - 1
                            iNextZ% = iNextZ% + 1
                            iNextX% = iNextX% - 1
                            iNextX% = iNextX% + 1
                            iNextY% = iNextY% - 1
                            iNextY% = iNextY% + 1
                
                ' CHECK IF NEXT SPACE IS EMPTY
                If arrMap
(iNextX%
, iNextY%
, iNextZ%
).Typ 
= c_iMapType_Empty 
Then                     ' SPACE IS EMPTY
                    ' DRAW HERE
                    
                    iCount% = iCount% + 1
                    iX% = iNextX%
                    iY% = iNextY%
                    iZ% = iNextZ%
                    
                    ' GET NEXT COLOR AND DRAW BLOCK
                    DoCycleColor iColorScheme%, iNextColor&
                    arrMap(iX%, iY%, iZ%).Typ = c_iMapType_Wall
                    arrMap(iX%, iY%, iZ%).Color1 = iNextColor&
                    
                    ' HAVE WE PLACED MAX # OF BLOCKS?
                        bFinished = TRUE
                    ' SPACE IS OCCUPIED
                    ' SEE IF WE HAVE ANY OPEN SPACES TO MOVE TO
                    iOpen% = 0
                        If arrMap
(iX%
, iY%
, iZ% 
- 1).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX%
, iY%
, iZ% 
+ 1).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX% 
- 1, iY%
, iZ%
).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX% 
+ 1, iY%
, iZ%
).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX%
, iY% 
- 1, iZ%
).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                        If arrMap
(iX%
, iY% 
+ 1, iZ%
).Typ 
= c_iMapType_Empty 
Then                             iOpen% = iOpen% + 1
                    
                    ' QUIT IF NO OPEN SPACES AVAILABLE
                        ' NOWHERE TO GO, EXIT
                        bFinished = TRUE
                
 
        ' PLOT GRAPHICS TO SCREEN
        DrawIsometricScreen arrMap()
        
        Input "Type q to quit? ", in$
         
            bQuit = TRUE
        
    
    
    IsometricDemo2 = sResult
 
' /////////////////////////////////////////////////////////////////////////////
 
    Dim RoutineName 
As String: RoutineName 
= "IsometricDemo3"     Dim arrMap
(m_iMapMinX 
To m_iMapMaxX
, m_iMapMinY 
To m_iMapMaxY
, m_iMapMinZ 
To m_iMapMaxZ
) As MapBlockType
     Dim iDirection% 
' direction player's nose is pointing     Dim iTotal% 
' compute total available spaces     Dim iCount% 
' count # of spaces searched     
    
    
    ' =============================================================================
    ' INITIALIZE
    'Screen _NewImage(1024, 720, 32) : _ScreenMove _Middle
    
    ' -----------------------------------------------------------------------------
    ' INITIALIZE MAP TO EMPTY
    ClearIsometricMap arrMap()
    
    ' -----------------------------------------------------------------------------
    ' DRAW FLOOR
    For iLoopZ% 
= m_iMapMinZ 
To m_iMapMinZ
         For iLoopX% 
= m_iMapMinX 
To m_iMapMaxX
             For iLoopY% 
= m_iMapMinY 
To m_iMapMaxY
                 arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iMapType_Floor_Tiled
                arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1 = cGray&
                arrMap(iLoopX%, iLoopY%, iLoopZ%).Color2 = cLightGray&
 
    ' -----------------------------------------------------------------------------
    ' DRAW A TALL HOLLOW PYRAMID
        iX% = 5
        iY% = 10
        iZ% = 1
        iLevelSize% = 4
        
        iPosX1% = iX%
        iPosX2% = iX% + 7
        iPosY1% = iY%
        iPosY2% = iY% + 7
        iNextColor& = cRed&
        iColorScheme% = 1 ' 1 = Rainbow6 #1, 9 = Rainbow6 #2, etc.
        iLevelCount% = 0
        
        bContinue = TRUE
            ' PLOT NEXT LEVEL
            'For iLoopX% = iPosX1% To iPosX2%
            '   For iLoopY% = iPosY1% To iPosY2%
            '       arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iMapType_Wall
            '       arrMap(iLoopX%, iLoopY%, iZ%).Color1 = iNextColor&
            '   Next iLoopY%
            'Next iLoopX%
            
            ' Draw front/back walls
            For iLoopX% 
= iPosX1% 
To iPosX2%
                 iLoopY% = iPosY1%
                arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iMapType_Wall
                arrMap(iLoopX%, iLoopY%, iZ%).Color1 = iNextColor&
                arrMap(iLoopX%, iLoopY%, iZ%).AlphaOverride = 255
                
                iLoopY% = iPosY2%
                arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iMapType_Wall
                arrMap(iLoopX%, iLoopY%, iZ%).Color1 = iNextColor&
                arrMap(iLoopX%, iLoopY%, iZ%).AlphaOverride = 255
            
            ' Draw left/right walls
            For iLoopY% 
= iPosY1% 
To iPosY2%
                 iLoopX% = iPosX1%
                arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iMapType_Wall
                arrMap(iLoopX%, iLoopY%, iZ%).Color1 = iNextColor&
                arrMap(iLoopX%, iLoopY%, iZ%).AlphaOverride = 255
                
                iLoopX% = iPosX2%
                arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iMapType_Wall
                arrMap(iLoopX%, iLoopY%, iZ%).Color1 = iNextColor&
                arrMap(iLoopX%, iLoopY%, iZ%).AlphaOverride = 255
            
            ' Add a door to middle of right wall
            iX% = iPosX1% + ((iPosX2% - iPosX1%) \ 2)
            arrMap(iX%, iPosY2%, iZ%).Typ = c_iMapType_Empty
            
            ' Add a door to middle of front wall
            iY% = iPosY1% + ((iPosY2% - iPosY1%) \ 2)
            arrMap(iPosX2%, iY%, iZ%).Typ = c_iMapType_Empty
            
            ' MOVE UP A LEVEL
            iLevelCount% = iLevelCount% + 1
            If iLevelCount% 
> iLevelSize% 
Then                 iLevelCount% = 0
                iPosX1% = iPosX1% + 1
                iPosX2% = iPosX2% - 1
                iPosY1% = iPosY1% + 1
                iPosY2% = iPosY2% - 1
            
            ' QUIT AFTER WE REACH THE TOP
            If (iPosX1% 
<= iPosX2%
) And (iPosY1% 
<= iPosY2%
) Then                 iZ% = iZ% + 1
                DoCycleColor iColorScheme%, iNextColor&
                    bContinue = FALSE
                bContinue = FALSE
            
    
    ' -----------------------------------------------------------------------------
    ' DRAW FRAME AROUND ENTIRE SPACE (TOP)
    
    For iLoopX% 
= m_iMapMinX 
+ 3 To m_iMapMaxX 
- 3         arrMap(iLoopX%, m_iMapMaxY - 3, m_iMapMaxZ).Typ = c_iMapType_Wall
        arrMap(iLoopX%, m_iMapMaxY - 3, m_iMapMaxZ).Color1 = cPurple&
        
        arrMap(iLoopX%, m_iMapMinY + 3, m_iMapMaxZ).Typ = c_iMapType_Wall
        arrMap(iLoopX%, m_iMapMinY + 3, m_iMapMaxZ).Color1 = cCyan&
    
    For iLoopY% 
= m_iMapMinY 
+ 3 To m_iMapMaxY 
- 3         arrMap(m_iMapMinX + 3, iLoopY%, m_iMapMaxZ).Typ = c_iMapType_Wall
        arrMap(m_iMapMinX + 3, iLoopY%, m_iMapMaxZ).Color1 = cOrange&
        
        arrMap(m_iMapMaxX - 3, iLoopY%, m_iMapMaxZ).Typ = c_iMapType_Wall
        arrMap(m_iMapMaxX - 3, iLoopY%, m_iMapMaxZ).Color1 = cLime&
    
    ' -----------------------------------------------------------------------------
    ' DRAW FRAME AROUND ENTIRE SPACE (MIDDLE)
    
    For iLoopX% 
= m_iMapMinX 
+ 2 To m_iMapMaxX 
- 2         arrMap(iLoopX%, m_iMapMaxY - 2, m_iMapMidZ).Typ = c_iMapType_Wall
        arrMap(iLoopX%, m_iMapMaxY - 2, m_iMapMidZ).Color1 = cDodgerBlue&
        
        arrMap(iLoopX%, m_iMapMinY + 2, m_iMapMidZ).Typ = c_iMapType_Wall
        arrMap(iLoopX%, m_iMapMinY + 2, m_iMapMidZ).Color1 = cDeepPurple&
    
    For iLoopY% 
= m_iMapMinY 
+ 2 To m_iMapMaxY 
- 2         arrMap(m_iMapMinX + 2, iLoopY%, m_iMapMidZ).Typ = c_iMapType_Wall
        arrMap(m_iMapMinX + 2, iLoopY%, m_iMapMidZ).Color1 = cDarkRed&
        
        arrMap(m_iMapMaxX - 2, iLoopY%, m_iMapMidZ).Typ = c_iMapType_Wall
        arrMap(m_iMapMaxX - 2, iLoopY%, m_iMapMidZ).Color1 = cGold&
    
    ' -----------------------------------------------------------------------------
    ' DRAW FRAME AROUND ENTIRE SPACE (BOTTOM)
    
    For iLoopX% 
= m_iMapMinX 
+ 1 To m_iMapMaxX 
- 1         arrMap(iLoopX%, m_iMapMaxY - 1, m_iMapMinZ + 1).Typ = c_iMapType_Wall
        arrMap(iLoopX%, m_iMapMaxY - 1, m_iMapMinZ + 1).Color1 = cSeaBlue&
        
        arrMap(iLoopX%, m_iMapMinY + 1, m_iMapMinZ + 1).Typ = c_iMapType_Wall
        arrMap(iLoopX%, m_iMapMinY + 1, m_iMapMinZ + 1).Color1 = cChartreuse&
    
    For iLoopY% 
= m_iMapMinY 
+ 1 To m_iMapMaxY 
- 1         arrMap(m_iMapMinX + 1, iLoopY%, m_iMapMinZ + 1).Typ = c_iMapType_Wall
        arrMap(m_iMapMinX + 1, iLoopY%, m_iMapMinZ + 1).Color1 = cOrangeRed&
        
        arrMap(m_iMapMaxX - 1, iLoopY%, m_iMapMinZ + 1).Typ = c_iMapType_Wall
        arrMap(m_iMapMaxX - 1, iLoopY%, m_iMapMinZ + 1).Color1 = cDeepSkyBlue&
    
    ' -----------------------------------------------------------------------------
    ' FIND START POSITION
    iX% = RandomNumber(m_iMapMinX, m_iMapMaxX)
    iY% = RandomNumber(m_iMapMinY, m_iMapMaxY)
    iZ% = 1 ' RandomNumber(m_iMapMinZ, m_iMapMaxZ)
    
    ' MAKE SURE IT'S EMPTY
    If arrMap
(iX%
, iY%
, iZ%
).Typ 
= c_iMapType_Empty 
Then         bFound = TRUE
        ' IF NOT EMPTY THEN TRY TO FIND AN EMPTY SPOT
        iTotal% = ((m_iMapMaxX - m_iMapMinX) + 1) * ((m_iMapMaxY - m_iMapMinY) + 1) * ((m_iMapMaxZ - m_iMapMinZ) + 1)
        iCount% = 0
        bFound = FALSE
            iX% = iX% + 1
                ' reset x and move to next y
                iX% = m_iMapMinX
                iY% = iY% + 1
                    ' reset y and move to next z
                    iY% = m_iMapMinY
                    iZ% = iZ% + 1
                        ' RESET Z AND SEE IF WE HAVE CHECKED EVERYTHING
                        iZ% = m_iMapMinZ
                        iCount% = iCount% + 1
                            ' NONE FOUND, EXIT
                        iCount% = iCount% + 1
                    iCount% = iCount% + 1
                iCount% = iCount% + 1
            If arrMap
(iX%
, iY%
, iZ%
).Typ 
= c_iMapType_Empty 
Then                 ' FOUND AN EMPTY SPACE, EXIT
                bFound = TRUE
    
        ' PLACE PLAYER
        iMyColor& = cRed&
        iColorScheme% = 2
        
        ' PICK A DIRECTION (SIMPLE FOR NOW, LEFT OR RIGHT)
            iDirection% = c_iDir_Right
            iDirection% = c_iDir_Left
        
        ' RESET MOVEMENT VARIABLES
        bMoving = FALSE
        bMoved = FALSE
        
        ' RESET INPUT
        iLastKey = c_iKeyDown_Enter
        
        ' DRAW PLAYER
        arrMap(iX%, iY%, iZ%).Typ = c_iMapType_Player1 ' c_iMapType_Wall
        arrMap(iX%, iY%, iZ%).Color1 = iMyColor&
        arrMap(iX%, iY%, iZ%).AlphaOverride = 255
        
        ' =============================================================================
        ' MAIN LOOP
        bFinished = FALSE
            ' PLOT GRAPHICS TO SCREEN
            ComputeVisible arrMap(), iX%, iY%, iZ%
            DrawIsometricScreen arrMap()
            
            ' SHOW INSTRUCTIONS / COORDINATES ON SCREEN
            Locate 3, 1: 
Print "CRSR RIGHT/LEFT MOVES X=" + cstr$
(iX%
)             Locate 4, 1: 
Print "CRSR UP   /DOWN MOVES Y=" + cstr$
(iY%
)             Locate 5, 1: 
Print "PAGE UP   /DOWN MOVES Z=" + cstr$
(iZ%
)             
            ' SHOW 2D MINI MAP ON SCREEN
            For iLoopX% 
= m_iMapMinX 
To m_iMapMaxX
                 For iLoopY% 
= m_iMapMinY 
To m_iMapMaxY
                     iDrawX% = (iLoopX% * 4) + 20
                    iDrawY% = (iLoopY% * 4) + 200
                    If arrMap
(iLoopX%
, iLoopY%
, iZ%
).Typ 
= c_iMapType_Wall 
Then                         DrawBox iDrawX%, iDrawY%, 4, arrMap(iLoopX%, iLoopY%, iZ%).Color1
                        
                    ElseIf arrMap
(iLoopX%
, iLoopY%
, iZ%
).Typ 
= c_iMapType_Player1 
Then                         DrawBox iDrawX%, iDrawY%, 4, arrMap(iLoopX%, iLoopY%, iZ%).Color1
                        
                        DrawBox iDrawX%, iDrawY%, 4, cBlack&
            
            ' GET KEYBOARD INPUT
                If iLastKey 
<> c_iKeyDown_Up 
Then                     iLastKey = c_iKeyDown_Up
                    iDirection% = c_iDir_Back
                    bMoved = TRUE
                If iLastKey 
<> c_iKeyDown_Down 
Then                     iLastKey = c_iKeyDown_Down
                    iDirection% = c_iDir_Forward
                    bMoved = TRUE
                If iLastKey 
<> c_iKeyDown_Left 
Then                     iLastKey = c_iKeyDown_Left
                    iDirection% = c_iDir_Left
                    bMoved = TRUE
                If iLastKey 
<> c_iKeyDown_Right 
Then                     iLastKey = c_iKeyDown_Right
                    iDirection% = c_iDir_Right
                    bMoved = TRUE
                If iLastKey 
<> c_iKeyDown_PgUp 
Then                     iLastKey = c_iKeyDown_PgUp
                    iDirection% = c_iDir_Up
                    bMoved = TRUE
                If iLastKey 
<> c_iKeyDown_PgDn 
Then                     iLastKey = c_iKeyDown_PgDn
                    iDirection% = c_iDir_Down
                    bMoved = TRUE
                If iLastKey 
<> c_iKeyDown_Spacebar 
Then                     iLastKey = c_iKeyDown_Spacebar
                    'bMoving = IIF(bMoving, False, True)
                        bMoving = FALSE
                        bMoving = TRUE
                iLastKey = -1
            
            ' --------------------------------------------------------------------------------
            ' ERASE OLD POSITION
            ' --------------------------------------------------------------------------------
            arrMap(iX%, iY%, iZ%).Typ = c_iMapType_Empty
            arrMap(iX%, iY%, iZ%).Color1 = cEmpty&
            arrMap(iX%, iY%, iZ%).AlphaOverride = 255
            
            ' --------------------------------------------------------------------------------
            ' MOVE PLAYER BASED ON DIRECTION
            ' --------------------------------------------------------------------------------
            'IF bMoved=TRUE THEN
                bMoved = FALSE
                
                        iNewX% = iX%
                        iNewY% = iY%
                        iNewZ% = iZ% - 1
                            iNewZ% = m_iMapMaxZ
                        If arrMap
(iNewX%
, iNewY%
, iNewZ%
).Typ 
<> c_iMapType_Empty 
Then                             iDirection% = c_iDir_Up
                            iNewZ% = iZ%
                        
                        iNewX% = iX%
                        iNewY% = iY%
                        iNewZ% = iZ% + 1
                            iNewZ% = m_iMapMinZ
                        If arrMap
(iNewX%
, iNewY%
, iNewZ%
).Typ 
<> c_iMapType_Empty 
Then                             iDirection% = c_iDir_Down
                            iNewZ% = iZ%
                        
                        iNewX% = iX% - 1
                        iNewY% = iY%
                        iNewZ% = iZ%
                            iNewX% = m_iMapMaxX
                        If arrMap
(iNewX%
, iNewY%
, iNewZ%
).Typ 
<> c_iMapType_Empty 
Then                             iDirection% = c_iDir_Right
                            iNewX% = iX%
                        
                        iNewX% = iX% + 1
                        iNewY% = iY%
                        iNewZ% = iZ%
                            iNewX% = m_iMapMinX
                        If arrMap
(iNewX%
, iNewY%
, iNewZ%
).Typ 
<> c_iMapType_Empty 
Then                             iDirection% = c_iDir_Left
                            iNewX% = iX%
                        
                        iNewX% = iX%
                        iNewY% = iY% - 1
                        iNewZ% = iZ%
                            iNewY% = m_iMapMaxY
                        If arrMap
(iNewX%
, iNewY%
, iNewZ%
).Typ 
<> c_iMapType_Empty 
Then                             iDirection% = c_iDir_Forward
                            iNewY% = iY%
                        
                        iNewX% = iX%
                        iNewY% = iY% + 1
                        iNewZ% = iZ%
                            iNewY% = m_iMapMinY
                        If arrMap
(iNewX%
, iNewY%
, iNewZ%
).Typ 
<> c_iMapType_Empty 
Then                             iDirection% = c_iDir_Back
                            iNewY% = iY%
                        
                        'iNewX% = iX%
                        'iNewY% = iY%
                        'iNewZ% = iZ%
                
                ' SAVE NEW POSITION
                iX% = iNewX%
                iY% = iNewY%
                iZ% = iNewZ%
            
            ' REDRAW AT CURRENT POSITION
            DoCycleColor iColorScheme%, iMyColor&
            arrMap(iX%, iY%, iZ%).Typ = c_iMapType_Player1 ' c_iMapType_Wall
            arrMap(iX%, iY%, iZ%).Color1 = iMyColor&
            arrMap(iX%, iY%, iZ%).AlphaOverride = 255
            
        
        sResult = "Could not find an empty space to start player."
    
    ' FINISH UP AND EXIT
    IsometricDemo3$ = sResult
 
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN GRAPHICS FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
' =============================================================================
' LET'S GET THE COORDINATES STRAIGHT!
' Coordinates are arrMap(x,y,z)
'           ________________
'          /|e            /|e
'         / |            / |
'        /  |           /  |z-axis
'       /   |          /   |
'      /    /---------/----/
'     /    / a       /   b/
'    /    /         /    /
'   |--------------|    /
'   |f  /         g|   / y-axis
'   |  /           |  /
'   | /            | /
'   |/c           d|/
'   ----------------
'      x-axis
'
' POINT    ( X, Y, Z)
' a        ( 0, 0, 0)
' b        (32, 0, 0)
' c        ( 0,32, 0)
' d        (32,32, 0)
' e        ( 0, 0,32)
' f        ( 0,32,32)
' g        (32,32,32)
' =============================================================================
 
' /////////////////////////////////////////////////////////////////////////////
' INITIALIZE MAP TO EMPTY
 
'ClearIsometricMap arrMap()
Sub ClearIsometricMap 
(arrMap
( m_iMapMinX 
To m_iMapMaxX 
, m_iMapMinY 
To m_iMapMaxY 
, m_iMapMinZ 
To m_iMapMaxZ
) As MapBlockType
)     Dim RoutineName 
As String: RoutineName 
= "ClearIsometricMap"     
    For iLoopZ% 
= m_iMapMinZ 
To m_iMapMaxZ
         For iLoopX% 
= m_iMapMinX 
To m_iMapMaxX
             For iLoopY% 
= m_iMapMinY 
To m_iMapMaxY
                 arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iMapType_Empty
                arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
 
 
' /////////////////////////////////////////////////////////////////////////////
' Determine which squares are visible in isometric map
 
' arrMap(x,y,z) = 3D array map of world
' iX% = player's X positon
' iY% = player's Y position
' iZ% = player's Z position
 
Sub ComputeVisible 
(arrMap
( m_iMapMinX 
To m_iMapMaxX 
, m_iMapMinY 
To m_iMapMaxY 
, m_iMapMinZ 
To m_iMapMaxZ
) As MapBlockType
, iX%
, iY%
, iZ%
)     
    
    ' CALCULATE PLAYER'S 2-D POSITION
    iPX1% = iX% * m_iGridSize + cGridOffsetX
    iPY1% = iY% * m_iGridSize + cGridOffsetY
    iPZ1% = iZ% * m_iGridSize + cGridOffsetZ
    iPlayer2Dx = CX2I(iPX1%, iPY1%) + cScreenOffsetX
    iPlayer2Dy = (CY2I(iPX1%, iPY1%) + cScreenOffsetY) - iPZ1%
    'fquad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, _RGB32(r, g, b, alpha&)
    
    For iLoopX% 
= m_iMapMinX 
To m_iMapMaxX
         For iLoopY% 
= m_iMapMinY 
To m_iMapMaxY
             For iLoopZ% 
= m_iMapMinZ 
To m_iMapMaxZ
                 ' If space has a brick
                ' and its 2D (X,Y) is > Player's 2D (X,Y)
                ' then make the brick transparent
                If arrMap
(iLoopX%
, iLoopY%
, iLoopZ%
).Typ 
= c_iMapType_Wall 
Then                     ' CALCULATE BRICK'S 2-D POSITION
                    iPX1% = iLoopX% * m_iGridSize + cGridOffsetX
                    iPY1% = iLoopY% * m_iGridSize + cGridOffsetY
                    iPZ1% = iLoopZ% * m_iGridSize + cGridOffsetZ
                    iBrick2Dx = CX2I(iPX1%, iPY1%) + cScreenOffsetX
                    iBrick2Dy = (CY2I(iPX1%, iPY1%) + cScreenOffsetY) - iPZ1%
                    'fquad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, _RGB32(r, g, b, alpha&)
                    
                    'If iLoopZ% >= iZ% Then
                    'If iLoopX% >= iX% Then
                        If (iPlayer2Dy 
>= (iBrick2Dy 
- m_iGridSize
)) And (iPlayer2Dy 
<= (iBrick2Dy 
+ m_iGridSize
)) Then                             If (iPlayer2Dx 
>= (iBrick2Dx 
- m_iGridSize
)) And (iPlayer2Dx 
<= (iBrick2Dx 
+ m_iGridSize
)) Then                                 arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 86
                                arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
                            arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
                    'End If
                    'End If
                    arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
 
' /////////////////////////////////////////////////////////////////////////////
' Draw the map in 3D Isometic Perspective
 
' Parameters:
' arrMap(x,y,z) = 3D array map of world
' iX% = player's X positon
' iY% = player's Y position
' iZ% = player's Z position
 
'DrawIsometricScreen arrMap()
Sub DrawIsometricScreen 
(arrMap
( m_iMapMinX 
To m_iMapMaxX 
, m_iMapMinY 
To m_iMapMaxY 
, m_iMapMinZ 
To m_iMapMaxZ
) As MapBlockType
)     Dim RoutineName 
As String: RoutineName 
= "DrawIsometricScreen"     
    alpha& = 255
    bTile = FALSE
    For iLoopZ% 
= m_iMapMinZ 
To m_iMapMaxZ
         For iLoopX% 
= m_iMapMinX 
To m_iMapMaxX
             For iLoopY% 
= m_iMapMinY 
To m_iMapMaxY
                 
                ' CALCULATE POSITION
                iPosZ1% = iLoopZ% * m_iGridSize + cGridOffsetZ
                iPosX1% = iLoopX% * m_iGridSize + cGridOffsetX
                iPosY1% = iLoopY% * m_iGridSize + cGridOffsetY
                iPosX2% = iPosX1% + m_iGridSize
                iPosY2% = iPosY1% + m_iGridSize
                
                ' DETERMINE COLOR
                If arrMap
(iLoopX%
, iLoopY%
, iLoopZ%
).Typ 
= c_iMapType_Floor_Tiled 
Then                         iColor = arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
                        bTile = FALSE
                        iColor = arrMap(iLoopX%, iLoopY%, iLoopZ%).Color2
                        bTile = TRUE
                ElseIf arrMap
(iLoopX%
, iLoopY%
, iLoopZ%
).Typ 
= c_iMapType_Wall 
Then                     iColor = arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
                    alpha& = arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride
                    
                ElseIf arrMap
(iLoopX%
, iLoopY%
, iLoopZ%
).Typ 
= c_iMapType_Player1 
Then                     iColor = arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
                    alpha& = 255
                    
                ElseIf arrMap
(iLoopX%
, iLoopY%
, iLoopZ%
).Typ 
= c_iMapType_Player2 
Then                     iColor = arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
                    alpha& = 255
                    
                ElseIf arrMap
(iLoopX%
, iLoopY%
, iLoopZ%
).Typ 
= c_iMapType_Water 
Then                     'TODO: transparent for water
                    iColor = cEmpty&
                    alpha& = 64
                    
                ElseIf arrMap
(iLoopX%
, iLoopY%
, iLoopZ%
).Typ 
= c_iMapType_Window 
Then                     'TODO: transparent for windows
                    iColor = cEmpty&
                    alpha& = 64
                    
                    iColor = cEmpty&
                
                ' PLOT NEXT BLOCK
                    'IsoLine3D(x,      y,       x2,      y2,      z,       iHeight,     xoffset,        yoffset,        iColor As _Unsigned Long, alpha&)
                    IsoLine3D iPosX1%, iPosY1%, iPosX2%, iPosY2%, iPosZ1%, m_iGridSize, cScreenOffsetX, cScreenOffsetY, iColor, alpha&
                
    
 
' /////////////////////////////////////////////////////////////////////////////
' RETURNS MAP AS TEXT
 
'Input "See a text dump (y/n)? ", in$
'If LCase$(in$) = LCase$("y") Then
'    Print MapToText$( arrMap() )
'End If
Function MapToText$ 
(arrMap
( m_iMapMinX 
To m_iMapMaxX 
, m_iMapMinY 
To m_iMapMaxY 
, m_iMapMinZ 
To m_iMapMaxZ
) As MapBlockType
)  
    sResult = ""
 
    ' FIND USED BOUNDARIES OF MAP
    iMinX% = -1
    iMaxX% = -1
    iMinY% = -1
    iMaxY% = -1
    iMinZ% = -1
    iMaxZ% = -1
                iType% = arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ
                If iType% 
<> c_iMapType_Empty 
And iType% 
<> c_iMapType_Floor_Tiled 
Then                         iMinX% = iLoopX%
                        iMinY% = iLoopY%
                        iMinZ% = iLoopZ%
                        iMaxX% = iLoopX%
                        iMaxY% = iLoopY%
                        iMaxZ% = iLoopZ%
 
    ' GENERATE OUTPUT
    For iLoopZ% 
= iMinZ% 
To iMaxZ%
         sResult 
= sResult 
+ "-------------------------------------------------------------------------------" + Chr$(13)        sResult 
= sResult 
+ "Map Z=" + cstr$
(iLoopZ%
) + ":" + Chr$(13)        sResult 
= sResult 
+ "-------------------------------------------------------------------------------" + Chr$(13)        For iLoopY% 
= iMinY% 
To iMaxY%
             sLine = ""
            For iLoopX% 
= iMinX% 
To iMaxX%
                 iType% = arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ
                iColor1& = arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
                iColor2& = arrMap(iLoopX%, iLoopY%, iLoopZ%).Color2
                iColor3& = arrMap(iLoopX%, iLoopY%, iLoopZ%).Color3
                
                If iType% 
= c_iMapType_Empty 
Then                     sLine = sLine + " "
                        sLine = sLine + " "
                        sLine = sLine + "#"
            sResult 
= sResult 
+ sLine 
+ Chr$(13) 
        sResult 
= sResult 
+ Chr$(13) 
    MapToText$ = sResult
 
' /////////////////////////////////////////////////////////////////////////////
 
    CX2I = x - y
 
' /////////////////////////////////////////////////////////////////////////////
 
    CY2I = (x + y) / 2
 
' /////////////////////////////////////////////////////////////////////////////
' since we're drawing a diamond and not a square box, we can't use Line BF.
' We have to manually down the 4 points of the line.
 
    Line (CX2I
(x
, y
) + xoffset
, CY2I
(x
, y
) + yoffset
)-(CX2I
(x2
, y
) + xoffset
, CY2I
(x2
, y
) + yoffset
), iColor
     Line -(CX2I
(x2
, y2
) + xoffset
, CY2I
(x2
, y2
) + yoffset
), iColor
     Line -(CX2I
(x
, y2
) + xoffset
, CY2I
(x
, y2
) + yoffset
), iColor
     Line -(CX2I
(x
, y
) + xoffset
, CY2I
(x
, y
) + yoffset
), iColor
     Paint (CX2I
(x
, y
) + xoffset
, CY2I
(x
, y
) + 4), iColor 
'and fill the diamond solid     Line (CX2I
(x
, y
) + xoffset
, CY2I
(x
, y
) + yoffset
)-(CX2I
(x2
, y
) + xoffset
, CY2I
(x2
, y
) + yoffset
), &HFFFFFFFF     Line -(CX2I
(x2
, y2
) + xoffset
, CY2I
(x2
, y2
) + yoffset
), &HFFFFFFFF     Line -(CX2I
(x
, y2
) + xoffset
, CY2I
(x
, y2
) + yoffset
), &HFFFFFFFF     Line -(CX2I
(x
, y
) + xoffset
, CY2I
(x
, y
) + yoffset
), &HFFFFFFFF  
' /////////////////////////////////////////////////////////////////////////////
' Like IsoLine, we're going to have to draw our lines manually.
' only in this case, we also need a Z coordinate to tell us how
' THICK/TALL/HIGH to make our tile
 
' MODIFIED by madscijr to draw a single block of height iHeight at Z axis
' MODIFIED by madscijr to accept an alpha& value to control transparency (where 0=fully transparent, 255=opaque)
 
''Sub IsoLine3D (x, y, x2, y2, z, xoffset, yoffset, iColor As _Unsigned Long)
'Sub IsoLine3D (x, y, x2, y2, z, iHeight, xoffset, yoffset, iColor As _Unsigned Long)
Sub IsoLine3D 
(x
, y
, x2
, y2
, z
, iHeight
, xoffset
, yoffset
, iColor 
As _Unsigned Long, alpha&
)     'dim iNewColor As _Unsigned Long
    
    
    ' Let's just do all the math first this time.
    ' We need to turn those 4 normal points into 4 isometric points (x, y, x1, y1)
    TempX1 = CX2I(x, y) + xoffset
    TempY1 = CY2I(x, y) + yoffset
    TempX2 = CX2I(x2, y) + xoffset
    TempY2 = CY2I(x2, y) + yoffset
    TempX3 = CX2I(x2, y2) + xoffset
    TempY3 = CY2I(x2, y2) + yoffset
    TempX4 = CX2I(x, y2) + xoffset
    TempY4 = CY2I(x, y2) + yoffset
    
    ' The top
    'fquad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, iColor
    fquad TempX1
, TempY1 
- z
, TempX2
, TempY2 
- z
, TempX3
, TempY3 
- z
, TempX4
, TempY4 
- z
, _RGB32(r
, g
, b
, alpha&
)    
        ' TODO: maybe change which sides gets shaded depending on the direction of the light source?
        
        ' draw the left side, shaded 75%
        'fquad TempX4, TempY4 - z, TempX4, TempY4 - z + iHeight, TempX3, TempY3 - z + iHeight, TempX3, TempY3 - z, _RGB32(.75 * r, .75 * g, .75 * b)
        fquad TempX4
, TempY4 
- z
, TempX4
, TempY4 
- z 
+ iHeight
, TempX3
, TempY3 
- z 
+ iHeight
, TempX3
, TempY3 
- z
, _RGB32(.75 * r
, .75 * g
, .75 * b
, alpha&
)        
        ' draw the right side,s haded 50%
        'fquad TempX3, TempY3 - z, TempX3, TempY3 - z + iHeight, TempX2, TempY2 - z + iHeight, TempX2, TempY2 - z, _RGB32(.5 * r, .5 * g, .5 * b)
        fquad TempX3
, TempY3 
- z
, TempX3
, TempY3 
- z 
+ iHeight
, TempX2
, TempY2 
- z 
+ iHeight
, TempX2
, TempY2 
- z
, _RGB32(.5 * r
, .5 * g
, .5 * b
, alpha&
)        ' no need to draw any height, if there isn't any.
 
' /////////////////////////////////////////////////////////////////////////////
' found at abandoned, outdated and now likely malicious qb64 dot net website
' don’t go there: http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/forum/index.php?topic=14425.0
 
 
 
' /////////////////////////////////////////////////////////////////////////////
' 2019-11-20 Steve saves some time with STATIC
' and saves and restores last dest
 
 
 
' /////////////////////////////////////////////////////////////////////////////
' original fill quad that may be at fault using Steve's fTri version
' need 4 non linear points (not all on 1 line) list them clockwise
' so x2, y2 is opposite of x4, y4
 
    ftri1 x1, y1, x2, y2, x4, y4, K
    ftri1 x3, y3, x2, y2, x4, y4, K
 
' /////////////////////////////////////////////////////////////////////////////
' update 2019-12-16 needs orig fTri
' need 4 non linear points (not all on 1 line)
' list them clockwise so x2, y2 is opposite of x4, y4
 
    ftri x1, y1, x2, y2, x3, y3, K
    ftri x3, y3, x4, y4, x1, y1, K
 
' /////////////////////////////////////////////////////////////////////////////
' DRAW A 2-D BOX
 
'SUB DrawBox (iX%, iY%, iSize%, iColor%)
Sub DrawBox 
(iX%
, iY%
, iSize%
, iColor&
)     Line (iX%
, iY%
)-(iX% 
+ iSize%
, iY% 
+ iSize%
), iColor&
, BF 
' Draw a solid box     'LINE (iX%, iY%)-(iX% + iSize%, iY% + iSize%), iColor%, BF ' Draw a solid box
    'LINE (60, 60)-(130, 100), iColor%, B ' Draw a box outline
 
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END GRAPHICS FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN GENERAL PURPOSE FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
' /////////////////////////////////////////////////////////////////////////////
 
    'cstr$ = LTRIM$(RTRIM$(STR$(myValue)))
 
' /////////////////////////////////////////////////////////////////////////////
 
 
' /////////////////////////////////////////////////////////////////////////////
 
    ''cstr$ = LTRIM$(RTRIM$(STR$(myValue)))
 
' /////////////////////////////////////////////////////////////////////////////
 
Function IIF 
(Condition
, IfTrue
, IfFalse
)  
' /////////////////////////////////////////////////////////////////////////////
 
Function IIFSTR$ 
(Condition
, IfTrue$
, IfFalse$
)     If Condition 
Then IIFSTR$ 
= IfTrue$ 
Else IIFSTR$ 
= IfFalse$
  
' /////////////////////////////////////////////////////////////////////////////
' From: Bitwise Manipulations By Steven Roman
' http://www.romanpress.com/Articles/Bitwise_R/Bitwise.htm
 
' Returns the 8-bit binary representation
' of an integer iInput where 0 <= iInput <= 255
 
 
    sResult = ""
 
            iInput = iInput \ 2
            'If iLoop = 4 Then sResult = " " + sResult
 
    GetBinary$ = sResult
 
' /////////////////////////////////////////////////////////////////////////////
' wonderfully inefficient way to read if a bit is set
' ival = GetBit256%(int we are comparing, int containing the bits we want to read)
 
' See also: GetBit256%, SetBit256%
 
    'DIM iTemp AS INTEGER
 
    iResult = FALSE
    bContinue = TRUE
 
        sNum = GetBinary$(iNum)
        sBit = GetBinary$(iBit)
                'if any of the bits in iBit are false, return false
                    iResult = FALSE
                    bContinue = FALSE
            iResult = TRUE
 
    GetBit256% = iResult
 
' /////////////////////////////////////////////////////////////////////////////
' From: Bitwise Manipulations By Steven Roman
' http://www.romanpress.com/Articles/Bitwise_R/Bitwise.htm
 
' Returns the integer that corresponds to a binary string of length 8
 
 
    iResult = 0
    strBinary = Replace$(sBinary, " ", "") ' Remove any spaces
        iResult 
= iResult 
+ 2 ^ iLoop 
* Val(Mid$(strBinary
, Len(strBinary
) - iLoop
, 1)) 
    GetIntegerFromBinary% = iResult
 
' /////////////////////////////////////////////////////////////////////////////
' By sMcNeill from https://www.qb64.org/forum/index.php?topic=896.0
 
        IsNum% = TRUE
        IsNum% = FALSE
 
' /////////////////////////////////////////////////////////////////////////////
' Split and join strings
' https://www.qb64.org/forum/index.php?topic=1073.0
 
'Combine all elements of in$() into a single string with delimiter$ separating the elements.
 
        result$ = result$ + delimiter$ + in$(i)
    join$ = result$
 
' /////////////////////////////////////////////////////////////////////////////
' ABS was returning strange values with type LONG
' so I created this which does not.
 
        LongABS& = 0 - lngValue
        LongABS& = lngValue
 
' /////////////////////////////////////////////////////////////////////////////
' Returns blank if successful else returns error message.
 
    'x = 1: y = 2: z$ = "Three"
 
 
                sError = "Error in PrintFile$ : File not found. Cannot append."
            Open sFileName 
For Output As #1 ' opens and clears an existing file or creates new empty file         ' WRITE places text in quotes in the file
        'WRITE #1, x, y, z$
        'WRITE #1, sText
 
        ' PRINT does not put text inside quotes
 
 
        'PRINT "File created with data. Press a key!"
        'K$ = INPUT$(1) 'press a key
 
        'OPEN sFileName FOR INPUT AS #2 ' opens a file to read it
        'INPUT #2, a, b, c$
        'CLOSE #2
 
        'PRINT a, b, c$
        'WRITE a, b, c$
 
    PrintFile$ = sError
 
' /////////////////////////////////////////////////////////////////////////////
' Generate random value between Min and Max.
 
    ' SET RANDOM SEED
    'Randomize ' Initialize random-number generator.
 
    ' GET RANDOM # Min%-Max%
    'RandomNumber = Int((Max * Rnd) + Min) ' generate number
 
    NumSpread% = (Max% - Min%) + 1
 
    RandomNumber% 
= Int(Rnd * NumSpread%
) + Min% 
' GET RANDOM # BETWEEN Max% AND Min% 
 
' /////////////////////////////////////////////////////////////////////////////
 
 
    sFileName = "c:\temp\maze_test_1.txt"
    sText 
= "Count" + Chr$(9) + "Min" + Chr$(9) + "Max" + Chr$(9) + "Random"    bAppend = FALSE
    sError = PrintFile$(sFileName, sText, bAppend)
        bAppend = TRUE
        iErrorCount = 0
 
        iMin = 0
        iMax = iCols - 1
            iNum = RandomNumber(iMin, iMax)
            sError = PrintFile$(sFileName, sText, bAppend)
                iErrorCount = iErrorCount + 1
                Print "    " + "Could not write to file " + Chr$(34) + sFileName 
+ Chr$(34) + "."  
        iMin = 0
        iMax = iRows - 1
            iNum = RandomNumber(iMin, iMax)
            sError = PrintFile$(sFileName, sText, bAppend)
                iErrorCount = iErrorCount + 1
                Print "    " + "Could not write to file " + Chr$(34) + sFileName 
+ Chr$(34) + "."  
        Print "Finished generating numbers. Errors: " + Str$(iErrorCount
)         Print "Error creating file " + Chr$(34) + sFileName 
+ Chr$(34) + "."  
    Input "Press <ENTER> to continue", sInput$
  
' /////////////////////////////////////////////////////////////////////////////
' FROM: String Manipulation
' http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/forum/index_topic_5964-0/
'
'SUMMARY:
'   Purpose:  A library of custom functions that transform strings.
'   Author:   Dustinian Camburides (dustinian@gmail.com)
'   Platform: QB64 (www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there])
'   Revision: 1.6
'   Updated:  5/28/2012
 
'SUMMARY:
'[Replace$] replaces all instances of the [Find] sub-string with the [Add] sub-string within the [Text] string.
'INPUT:
'Text: The input string; the text that's being manipulated.
'Find: The specified sub-string; the string sought within the [Text] string.
'Add: The sub-string that's being added to the [Text] string.
 
    ' VARIABLES:
    Dim lngLocation 
As Long ' The address of the [Find] substring within the [Text] string.     Dim strBefore 
As String ' The characters before the string to be replaced.     Dim strAfter 
As String ' The characters after the string to be replaced.  
    ' INITIALIZE:
    ' MAKE COPIESSO THE ORIGINAL IS NOT MODIFIED (LIKE ByVal IN VBA)
    Text2 = Text1
    Find2 = Find1
    Add2 = Add1
 
    lngLocation 
= InStr(1, Text2
, Find2
) 
    ' PROCESSING:
    ' While [Find2] appears in [Text2]...
        ' Extract all Text2 before the [Find2] substring:
        strBefore 
= Left$(Text2
, lngLocation 
- 1) 
        ' Extract all text after the [Find2] substring:
        strAfter 
= Right$(Text2
, ((Len(Text2
) - (lngLocation 
+ Len(Find2
) - 1)))) 
        ' Return the substring:
        Text2 = strBefore + Add2 + strAfter
 
        ' Locate the next instance of [Find2]:
        lngLocation 
= InStr(1, Text2
, Find2
) 
        ' Next instance of [Find2]...
 
    ' OUTPUT:
    Replace$ = Text2
 
' /////////////////////////////////////////////////////////////////////////////
' fantastically inefficient way to set a bit
 
' example use: arrMaze(iX, iY) = SetBit256%(arrMaze(iX, iY), cS, FALSE)
 
' See also: GetBit256%, SetBit256%
 
' newint=SetBit256%(oldint, int containing the bits we want to set, value to set them to)
 
        sNum = GetBinary$(iNum)
        sBit = GetBinary$(iBit)
            sVal = "1"
            sVal = "0"
        strResult = ""
                strResult = strResult + sVal
                strResult 
= strResult 
+ Mid$(sNum
, iLoop
, 1)        iResult = GetIntegerFromBinary%(strResult)
        iResult = iNum
 
    SetBit256% = iResult
 
' /////////////////////////////////////////////////////////////////////////////
' Split and join strings
' https://www.qb64.org/forum/index.php?topic=1073.0
'
' FROM luke, QB64 Developer
' Date: February 15, 2019, 04:11:07 AM »
'
' Given a string of words separated by spaces (or any other character),
' splits it into an array of the words. I've no doubt many people have
' written a version of this over the years and no doubt there's a million
' ways to do it, but I thought I'd put mine here so we have at least one
' version. There's also a join function that does the opposite
' array -> single string.
'
' Code is hopefully reasonably self explanatory with comments and a little demo.
' Note, this is akin to Python/JavaScript split/join, PHP explode/implode.
 
'Split in$ into pieces, chopping at every occurrence of delimiter$. Multiple consecutive occurrences
'of delimiter$ are treated as a single instance. The chopped pieces are stored in result$().
'
'delimiter$ must be one character long.
'result$() must have been REDIMmed previously.
 
Sub split 
(in$
, delimiter$
, result$
())     start = 1
            start = start + 1
        finish 
= InStr(start
, in$
, delimiter$
)        result$
(UBound(result$
)) = Mid$(in$
, start
, finish 
- start
)        start = finish + 1
 
' /////////////////////////////////////////////////////////////////////////////
 
 
 
    in$ = "this" + delim$ + "is" + delim$ + "a" + delim$ + "test"
    split in$, delim$, arrTest$()
 
    Print "Split test finished."  
' /////////////////////////////////////////////////////////////////////////////
 
    Input "Press <ENTER> to continue", in$
  
' /////////////////////////////////////////////////////////////////////////////
' WaitForKey "Press <ESC> to continue", 27, 0
' WaitForKey "Press <ENTER> to begin;", 13, 0
' waitforkey "", 65, 5
 
Sub WaitForKey 
(prompt$
, KeyCode&
, DelaySeconds%
)     ' SHOW PROMPT (IF SPECIFIED)
 
    ' WAIT FOR KEY
 
    ' PAUSE AFTER (IF SPECIFIED)
 
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END GENERAL PURPOSE FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN COLOR ROUTINES
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
' /////////////////////////////////////////////////////////////////////////////
' Receives:
' cycleColor = determines how foreColor, backColor are modified
' foreColor  = the foreground color
' backColor  = the background color (if needed)
 
' /////////////////////////////////////////////////////////////////////////////
' DoCycleColor colorScheme%, myColor&
 
' colorScheme = color scheme (value is alternated on subsequent calls)
' myColor     = the current color (value is incremented/decremented on subsequent calls)
 
' colorScheme values:
'  1 Rainbow6 #1
'  9 Rainbow6 #2
'  2 Rainbow18 #1
' 10 Rainbow18 #2
'  3 Grayscale #1
' 11 Grayscale #2
'  4 Grayscale #1
' 12 Grayscale #2
 
    ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
    ' CYCLE FORE COLOR
 
    ' 1, 5, 9 = simple rainbow
    If colorScheme 
= 1 Or colorScheme 
= 9 Then                 myColor = cOrange&
                myColor = cYellow&
                myColor = cGreen&
                myColor = cBlue&
                myColor = cPurple&
                myColor = cRed&
 
        ' 2, 6, 10 = complex rainbow
                myColor = cOrangeRed&
                myColor = cDarkOrange&
                myColor = cOrange&
                myColor = cGold&
                myColor = cYellow&
                myColor = cChartreuse&
                myColor = cLime&
                myColor = cMediumSpringGreen&
            Case cMediumSpringGreen&:
                 myColor = cCyan&
                myColor = cDeepSkyBlue&
                myColor = cDodgerBlue&
                myColor = cSeaBlue&
                myColor = cBlue&
                myColor = cBluePurple&
                myColor = cDeepPurple&
                myColor = cPurple&
                myColor = cPurpleRed&
                myColor = cRed&
 
        ' 3, 7, 11 = grayscale, ascending
                myColor = cDarkGray&
                myColor = cDimGray&
                myColor = cGray&
                myColor = cLightGray&
                myColor = cSilver&
                myColor = cWhite&
                'myColor = cBlack&
                myColor = cSilver&
 
                ' go in the other direction!
                    colorScheme = 4
                    colorScheme = 12
 
 
        ' 4, 8, 12 = grayscale, descending
                myColor = cSilver&
                myColor = cLightGray&
                myColor = cGray&
                myColor = cDimGray&
                myColor = cDarkGray&
                myColor = cBlack&
                myColor = cDarkGray&
 
                ' go in the other direction!
                    colorScheme = 3
                    colorScheme = 11
 
    
 
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END COLOR ROUTINES
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN COLOR FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
' NOTE: these are mostly negative numbers
'       and have to be forced to positive
'       when stored in the dictionary
'       (only cEmpty& should be negative)
 
 
    cOrangeRed& 
= _RGB32(255, 69, 0) 
    cDarkOrange& 
= _RGB32(255, 140, 0) 
    cOrange& 
= _RGB32(255, 165, 0) 
 
    cYellow& 
= _RGB32(255, 255, 0) 
    cChartreuse& 
= _RGB32(127, 255, 0) 
 
    cMediumSpringGreen& 
= _RGB32(0, 250, 154) 
 
    cDeepSkyBlue& 
= _RGB32(0, 191, 255) 
    cDodgerBlue& 
= _RGB32(30, 144, 255) 
    cSeaBlue& 
= _RGB32(0, 64, 255) 
 
    cBluePurple& 
= _RGB32(64, 0, 255) 
    cDeepPurple& 
= _RGB32(96, 0, 255) 
    cPurple& 
= _RGB32(128, 0, 255) 
    cPurpleRed& 
= _RGB32(128, 0, 192) 
    cDarkRed& 
= _RGB32(160, 0, 64) 
    cBrickRed& 
= _RGB32(192, 0, 32) 
    cDarkGreen& 
= _RGB32(0, 100, 0) 
 
    cOliveDrab& 
= _RGB32(107, 142, 35) 
    cLightPink& 
= _RGB32(255, 182, 193) 
    cHotPink& 
= _RGB32(255, 105, 180) 
    cDeepPink& 
= _RGB32(255, 20, 147) 
    cMagenta& 
= _RGB32(255, 0, 255) 
 
    cDimGray& 
= _RGB32(105, 105, 105) 
    cGray& 
= _RGB32(128, 128, 128) 
    cDarkGray& 
= _RGB32(169, 169, 169) 
    cSilver& 
= _RGB32(192, 192, 192) 
    cLightGray& 
= _RGB32(211, 211, 211) 
    cGainsboro& 
= _RGB32(220, 220, 220) 
    cWhiteSmoke& 
= _RGB32(245, 245, 245) 
    cWhite& 
= _RGB32(255, 255, 255) 
    cDarkBrown& 
= _RGB32(128, 64, 0) 
    cLightBrown& 
= _RGB32(196, 96, 0) 
    cKhaki& 
= _RGB32(240, 230, 140) 
    cEmpty& = -1
 
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END COLOR FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++