Solution to Lesson 12

( This code can be found at .\tutorial\Lesson12\SoundSlots.bas )

'* Simple Slot Machine V1.1
'* by Terry Ritchie
'* 08/15/22 - made for QB64 tutorial Lesson 10
'* 06/11/24 - Sound added for tutorial Lesson 12
'* Open source code - freely modify
'* Original author's name must remain intact

OPTION _EXPLICIT ' all variables must be declared

CONST FALSE = 0, TRUE = NOT FALSE
CONST SQUARE = 1, CIRC = 2, DIAMOND = 3, TRIANGLE1 = 4, TRIANGLE2 = 5, SPECIAL = 6
CONST RED = _RGB32(255, 0, 0)
CONST GREEN = _RGB32(0, 255, 0)
CONST BLUE = _RGB32(0, 0, 255)
CONST PURPLE = _RGB32(255, 0, 255)
CONST YELLOW = _RGB32(255, 255, 0)
CONST CYAN = _RGB32(0, 255, 255)
CONST GRAY = _RGB32(63, 63, 63)

TYPE ICONS '                            icon definition
    icon AS INTEGER '                   shape of icon
    value1 AS INTEGER '                 value if one shown
    value2 AS INTEGER '                 value if two shown
    value3 AS INTEGER '                 value if three shown
END TYPE

TYPE SOUNDS '                           game sound effects
    Ambient AS LONG '                   ambient casino background sound
    InsertCoin AS LONG '                coin being inserted into slot machine
    PullHandle AS LONG '                handle being pulled
    BeginWheelSpin AS LONG '            sound of wheels getting spun up
    WheelSpin AS LONG '                 wheels spinning
    WheelStop AS LONG '                 a wheel stopping
    Winner AS LONG '                    regular winning sound
    Jackpot AS LONG '                   jackpot winning sound
    JackpotCoins AS LONG '              jackpot coins dropping
END TYPE

DIM Icon(6) AS ICONS '                  array of the 6 icons available
DIM Wheel(3, 16) AS ICONS '             array of 3 wheels each containing 16 icons
DIM IWind%(3) '                         icon window x coordinate locations
DIM CoinDrop&(10) '                     10 different sounds of coins dropping
DIM SND AS SOUNDS '                     slot machine sound effects
DIM Count% '                            general purpose counter / value holder
DIM Score& '                            player score (LONG INT in case player wins big)
DIM Winner% '                           TRUE when player wins, FALSE otherwise
DIM KeyPress$ '                         player keyboard inputs
DIM i% '                                counter
DIM j% '                                counter

LoadSounds '                            load the game sounds
Icon(1).icon = SQUARE '                 each wheel contains 3
Icon(1).value3 = 25 '                   3 squares point
Icon(2).icon = CIRC '                   each wheel contains 3
Icon(2).value2 = 10 '                   2 circles points
Icon(2).value3 = 25 '                   3 circles points
Icon(3).icon = DIAMOND '                each wheel contains 3
Icon(3).value1 = 1 '                    1 diamond points
Icon(3).value2 = 5 '                    2 diamonds points
Icon(3).value3 = 10 '                   3 diamonds points
Icon(4).icon = TRIANGLE1 '              each wheel contain 3
Icon(4).value3 = 25 '                   3 up triangles points
Icon(5).icon = TRIANGLE2 '              each wheel contains 3
Icon(5).value3 = 25 '                   3 down triangles points
Icon(6).icon = SPECIAL '                each wheel contains 1
Icon(6).value3 = 500 '                  3 specials points
FOR i% = 1 TO 3 '                       cycle through the 3 wheels
    IWind%(i%) = (i% - 1) * 110 + 10 '  record x coordinate of icon window
    Count% = 0 '                        reset icon counter
   FOR j% = 1 TO 15 '                   cycle through 15 icons on the wheel
        Count% = Count% + 1 '           increment icon counter
       IF Count% = 6 THEN Count% = 1 '  reset icon counter when needed
        Wheel(i%, j%) = Icon(Count%) '  place icon at this position on wheel
   NEXT j%
    Wheel(i%, 16) = Icon(6) '           last position on wheel contains big payout icon
NEXT i%
Wheel(1, 0).value2 = 16 '               These variables are used to indicate which icon
Wheel(2, 0).value2 = 16 '               on each wheel is currently showing. since
Wheel(3, 0).value2 = 16 '               (x,0).value2 not used it has been repurposed.
SCREEN _NEWIMAGE(340, 340, 32) '        create game window
CLS , GRAY '                            clear window with gray background
_TITLE "Slot Machine" '                 give window a title
_SCREENMOVE _MIDDLE '                   move window to center of screen
_DELAY .2 '                             give it some time to get there
DrawIcon IWind%(1), SPECIAL '           draw special icon in all three icon windows
DrawIcon IWind%(2), SPECIAL
DrawIcon IWind%(3), SPECIAL
COLOR YELLOW, GRAY '                    yellow text on gray background
PRINT "                SLOT MACHINE"
LOCATE 9, 1: PRINT " ENTER to spin                 ESC to exit"
LOCATE 11, 1: PRINT "                  PAYOUTS"
PRINT
PRINT
"          3 Double Circles - 500"
PRINT "          3 Squares        -  25"
PRINT "          3 Triangles      -  25"
PRINT "          3 Circles        -  25"
PRINT "          2 Circles        -  10"
PRINT "          3 Diamonds       -  10"
PRINT "          2 Diamonds       -   5"
PRINT "          1 Diamond        -   1";
_SNDLOOP SND.Ambient
DO '                                       ** begin main game loop **
    Count% = 0 '                              reset general purpose variable
   LOCATE 9, 20 '                             position the text cursor
   PRINT USING "#####"; Score& '              print player's current score
   DO '                                       begin player input loop
       _LIMIT 5 '                             check for input 5 times per second
        KeyPress$ = INKEY$ '                  grab any key player may press
       IF KeyPress$ = CHR$(27) THEN ExitGame ' leave if player pressed escape key
       IF Winner% THEN '                      was last spin a winner?
            Count% = Count% + 1 '             yes, increment text flash counter
           IF Count% = 11 THEN Count% = 1 '   reset text flash counter if needed
           LOCATE 1, 17 '                     position the text cursor
           IF Count% < 6 THEN '               is text flash counter < 6?
               PRINT "  WINNER!!  "; '        yes, show winner text
           ELSE '                             no, it's > 5
               PRINT "            "; '        print nothing instead
           END IF
       END IF
   LOOP UNTIL KeyPress$ = CHR$(13) '          leave input loop when ENTER pressed
   _SNDSTOP SND.JackpotCoins '                stop jackpot coins if looping
   _SNDPLAY SND.InsertCoin '                  coin being inserted into machine
   _DELAY 1 '                                 wait for it to drop
   _SNDPLAY SND.PullHandle '                  pull handle sound
   _DELAY .7 '                                wait a bit while its being pulled
   _SNDPLAY SND.BeginWheelSpin '              spring release sound to start spinning
    Winner% = FALSE '                         reset winner flag
   LOCATE 1, 17 '                             position the text cursor
   PRINT "SLOT MACHINE"; '                    reset top text
    Score& = Score& - 1 '                     player used 1 point to play
    Count% = SpinWheels% '                    spin the wheels and get the result
   IF Count% > 0 THEN '                       did player win?
        Winner% = TRUE '                      yes, set the winner flag
        Score& = Score& + Count% '            add the winnings to the score
       IF Count% = 500 THEN '                 jackpot?
           _SNDPLAY SND.Jackpot '             yes, play jackpot bell
           _SNDLOOP SND.JackpotCoins '        start dropping massive coins
       ELSE '                                 no, other than jackpot
           _SNDPLAY SND.Winner '              play normal winner bell
           RANDOMIZE TIMER '                  seed random number generator
           FOR i% = 1 TO Count% '             count the number of coins won
               _SNDPLAY CoinDrop&(INT(RND * 10) + 1) ' drop a coin sound
               _DELAY .25 '                   4 coin drops per second
           NEXT i%
       END IF
   END IF
LOOP '                                     ** end main game loop **
'-------------------------------------------------------------------------------------------
FUNCTION SpinWheels% () '        spins the 3 icon wheels returning payout result

   SHARED Wheel() AS ICONS '    array of 3 wheels
   SHARED IWind() AS INTEGER '  array of icon window positions
   SHARED SND AS SOUNDS '       slot machine sound effects
   DIM icon1%, icon2%, icon3% ' the icons showing after spin complete
   DIM total% '                 the total of the icons showing
   DIM i% '                     general purpose counter

   _SNDLOOP SND.WheelSpin '                                        start wheel spin sound
   RANDOMIZE TIMER '                                               seed RND generator
    Wheel(1, 0).value1 = 16 + INT(RND * 16) '                      # of frames wheel 1 spins
    Wheel(2, 0).value1 = Wheel(1, 0).value1 + 16 + INT(RND * 16) ' # of frames wheel 2 spins
    Wheel(3, 0).value1 = Wheel(2, 0).value1 + 16 + INT(RND * 16) ' # of frames wheel 3 spins
   DO '                                                            spin the wheels
       _LIMIT 32 '                                                 32 frames per second
       FOR i% = 1 TO 3 '                                           cycle through the wheels
           IF Wheel(i%, 0).value1 > 0 THEN '                       is wheel still spinning?
                Wheel(i%, 0).value2 = Wheel(i%, 0).value2 + 1 '           go to next icon
               IF Wheel(i%, 0).value2 = 17 THEN Wheel(i%, 0).value2 = 1 ' reset icon
                Wheel(i%, 0).value1 = Wheel(i%, 0).value1 - 1 '           count down frames
               IF Wheel(i%, 0).value1 = 10 THEN _SNDPLAYCOPY SND.WheelStop ' play kerchunk
                DrawIcon IWind(i%), Wheel(i%, Wheel(i%, 0).value2).icon '    draw the icon
           END IF
       NEXT i%
       _DISPLAY '                                      only show icon when done drawing
   LOOP UNTIL Wheel(3, 0).value1 = 0 '                 leave when wheels have stopped
   _SNDSTOP SND.WheelSpin '                            stop wheel gears clicking sound
   _AUTODISPLAY '                                      display screen updates right away
    icon1% = Wheel(1, Wheel(1, 0).value2).icon '       record the three icons showing
    icon2% = Wheel(2, Wheel(2, 0).value2).icon
    icon3% = Wheel(3, Wheel(3, 0).value2).icon
    total% = Wheel(1, Wheel(1, 0).value2).value1 '     get value of icon 1
   IF icon1% = icon2% THEN '                           does 2nd icon match 1st?
        total% = Wheel(2, Wheel(2, 0).value2).value2 ' yes, get value of icon 2
   END IF
   IF icon1% = icon2% AND icon2% = icon3% THEN '       are all 3 icons the same?
        total% = Wheel(3, Wheel(3, 0).value2).value3 ' yes, get value of icon 3
   END IF
    SpinWheels% = total% '                             return the payout value
END FUNCTION
'-------------------------------------------------------------------------------------------
SUB DrawIcon (x%, icon%) ' draws a given icon within the given icon window x coordinate

   DIM y% '               the y coordinate position of the icon windows

    y% = 20 '                                                     20 pixels down from top
   LINE (x%, y%)-(x% + 100, y% + 100), _RGB32(0, 0, 0), BF '      draw the icon window
   SELECT CASE icon% '                                            which icon to draw?
       CASE SQUARE '                                              the blue square
           LINE (x% + 10, y% + 10)-(x% + 90, y% + 90), BLUE, BF ' draw the icon in window
       CASE CIRC '                                                the red circle
           CIRCLE (x% + 50, y% + 50), 40, RED '                   draw the icon
           PAINT (x% + 50, y% + 50), RED, RED
       CASE DIAMOND '                                             the green diamond
           LINE (x% + 50, y% + 10)-(x% + 90, y% + 50), GREEN '    draw the icon
           LINE -(x% + 50, y% + 90), GREEN
           LINE -(x% + 10, y% + 50), GREEN
           LINE -(x% + 50, y% + 10), GREEN
           PAINT (x% + 50, y% + 50), GREEN, GREEN
       CASE TRIANGLE1 '                                           the yellow triangle
           LINE (x% + 50, y% + 10)-(x% + 90, y% + 90), YELLOW '   draw the icon
           LINE -(x% + 10, y% + 90), YELLOW
           LINE -(x% + 49, y% + 10), YELLOW
           PAINT (x% + 49, y% + 50), YELLOW, YELLOW
       CASE TRIANGLE2 '                                           the purple triangle
           LINE (x% + 10, y% + 10)-(x% + 90, y% + 10), PURPLE '   draw the icon
           LINE -(x% + 50, y% + 90), PURPLE
           LINE -(x% + 10, y% + 10), PURPLE
           PAINT (x% + 50, y% + 50), PURPLE, PURPLE
       CASE SPECIAL '                                             the big payout icon
           CIRCLE (x% + 50, y% + 50), 40, CYAN '                  draw the icon
           PAINT (x% + 50, y% + 50), CYAN, CYAN
           CIRCLE (x% + 50, y% + 50), 20, BLUE
           PAINT (x% + 50, y% + 50), BLUE, BLUE
   END SELECT

END SUB
'-------------------------------------------------------------------------------------------
SUB LoadSounds () ' loads the game's sounds

   SHARED CoinDrop&() '   10 different sounds of coins dropping
   SHARED SND AS SOUNDS ' slot machine sound effects
   DIM s% '               counter
   DIM FilePath$ '        path to sound files

    FilePath$ = ".\tutorial\Lesson12\slots\" '                       path to sound files
    SND.Ambient = _SNDOPEN(FilePath$ + "casinoambient.ogg")
    SND.InsertCoin = _SNDOPEN(FilePath$ + "coininsert.ogg")
    SND.PullHandle = _SNDOPEN(FilePath$ + "pullhandle.ogg")
    SND.BeginWheelSpin = _SNDOPEN(FilePath$ + "wheelspinbegin.ogg")
    SND.WheelSpin = _SNDOPEN(FilePath$ + "wheelspin.ogg")
    SND.WheelStop = _SNDOPEN(FilePath$ + "wheelstop.ogg")
    SND.Winner = _SNDOPEN(FilePath$ + "winner.ogg")
    SND.Jackpot = _SNDOPEN(FilePath$ + "winnerwinner.ogg")
    SND.JackpotCoins = _SNDOPEN(FilePath$ + "coindropwinner.ogg")
   FOR s% = 1 TO 10
        CoinDrop&(s%) = _SNDOPEN(FilePath$ + "coindrop" + _TRIM$(STR$(s%)) + ".ogg")
   NEXT s%

END SUB
'-------------------------------------------------------------------------------------------
SUB ExitGame () ' remove assets from RAM then exit program

   SHARED CoinDrop&() '   10 different sounds of coins dropping
   SHARED SND AS SOUNDS ' slot machine sound effects
   DIM s% '               counter

   _SNDCLOSE SND.Ambient '        remove all sounds from RAM
   _SNDCLOSE SND.InsertCoin '     (always clean up after yourself before exiting)
   _SNDCLOSE SND.PullHandle
   _SNDCLOSE SND.BeginWheelSpin
   _SNDCLOSE SND.WheelSpin
   _SNDCLOSE SND.WheelStop
   _SNDCLOSE SND.Winner
   _SNDCLOSE SND.Jackpot
   _SNDCLOSE SND.JackpotCoins
   FOR s% = 1 TO 10
       _SNDCLOSE CoinDrop&(s%)
   NEXT s%
   SYSTEM '                       return to operating system

END SUB
'-------------------------------------------------------------------------------------------