Uh oh, Slime!

You find yourself trapped in a maze that is flooding with horrid #green #slime.  You had better bash those cursor keys and get out quickly!

Uh oh, Slime! is a simple maze game that uses the random maze generator.  Source code is provided below for your hacking fun.

5 levels of difficulty, so even your gran can play.

RUN!

You can download the source code and Windows Executable here, or find the The BBC BASIC Source code below:

     REM daft maze game
     REM Timothy Goliath Street
     REM superdecadegames.com
     REM ---------------------------
     REM VERSION HISTORY
     REM ---------------------------
     
VERSION$ = "1.0.0.1"
     REM 2015-05-03

     
MODE 10 : OFF :   OSCLI "escape off"
     PROC_preventResize

     REM find difficulty level
     
CASE FN_showIntro OF
       WHEN 
"1"
         MAZE_WIDTH% = 15
         MAZE_HEIGHT% = 12
         CELL_WIDTH% = 96

       WHEN "2"
         MAZE_WIDTH% = 30
         MAZE_HEIGHT% = 24
         CELL_WIDTH% = 48

       WHEN "3"
         MAZE_WIDTH% = 60
         MAZE_HEIGHT% = 48
         CELL_WIDTH% = 24

       WHEN "4"
         MAZE_WIDTH% = 90
         MAZE_HEIGHT% = 72
         CELL_WIDTH% = 18

       WHEN "5"
         MAZE_WIDTH% = 120
         MAZE_HEIGHT% = 96
         CELL_WIDTH% = 12

     ENDCASE

     
REM number of passes used by maze generator
     
MAZE_COUNTER_LIMIT% = MAZE_WIDTH% * MAZE_HEIGHT% * 90

     REM set up a maze array
     
DIM Maze%( MAZE_WIDTH%-1, MAZE_HEIGHT%-1 )

     _entrance% = 0 : REM position of the entrance

     
DIM player{ x%, y% }

     delay% = 8
     SLIME_CHANCE% = 3

     wins% = 0
     losses% = 0

     REPEAT

       PROC
_createMaze( Maze%(), _entrance% )

       REM player starts at the entrance
       
player.x% = _entrance% : player.y% = 1
       dead% = FALSE REM flag controls whether player is dead
       
won% = FALSE REM flag controls whether player has reached end
       
numSteps% = 0 : REM the number of steps gone by

       
REPEAT UNTIL INKEY(1) =-1

       REPEAT
         PROC
_drawMaze( Maze%() )
         PROC_drawPlayer( player.x%, player.y% )

         TIME = 0
         g% = INKEY(delay%)
         WAIT delay% - TIME
         
numSteps% += 1

         REM short delay before slime grows
         
IF numSteps% > 20 THEN
           PROC
_growSlime( Maze%() )
         ENDIF

         CASE 
g% OF
           WHEN 
139 : REM up
             
IF FN_canMove( Maze%(), player.x%, player.y%+1 ) THEN
               
player.y% += 1
             ENDIF

           WHEN 
136 : REM left
             
IF FN_canMove( Maze%(), player.x%-1, player.y% ) THEN
               
player.x% -= 1
             ENDIF

           WHEN 
137 : REM right
             
IF FN_canMove( Maze%(), player.x%+1, player.y% ) THEN
               
player.x% += 1
             ENDIF

           WHEN 
138 : REM down
             
IF FN_canMove( Maze%(), player.x%, player.y%-1 ) THEN
               
player.y% -= 1
             ENDIF

         ENDCASE

         
REM check for death
         
IF Maze%(player.x%, player.y%) = 2 THEN
           
dead% = TRUE
         ENDIF
         
REM check for victory
         
IF player.y% = MAZE_HEIGHT%-1 THEN
           
won% = TRUE
         ENDIF


       UNTIL 
dead% OR won%

       IF dead% losses% += 1 : PROC_showDead
       IF won% wins%+=1 : PROC_showWon

       PROC_clearMaze( Maze%() )
     UNTIL FALSE
     END



     
DEFPROC_showDead
     LOCAL g
     OSCLI "refresh on":OSCLI "refresh"
     COLOUR 1, 0,0,0 : COLOUR 129 : CLS
     COLOUR 
3, 0, 240, 0: COLOUR 3

     OSCLI "font Courier New, 44b"
     PRINTTAB(7,1) "OH NO! ":PRINTTAB(1,2)"THE SLIME GOT YOU!"
     OSCLI "font Courier New, 24"
     PRINTTAB(9)"wins: "STR$(wins%)" losses: "STR$(losses%)
     COLOUR 3, 200,200,200: COLOUR 3
     OSCLI "font Courier New, 18"
     PRINT '"  Press any key to start, or <SPACE> to reset."
     REPEAT UNTIL INKEY(1) = -1

     g = GET
     IF 
g= 32 RUN
     WAIT 
100
     ENDPROC


     
DEFPROC_showWon
     LOCAL g
     OSCLI "refresh on":OSCLI "refresh"
     COLOUR 1, 0,0,0 : COLOUR 129 : CLS
     COLOUR 
3, 0, 240, 0: COLOUR 3

     OSCLI "font Courier New, 44b"
     PRINTTAB(2,1) "EXCELLENT!":PRINTTAB(3,2)"YOU ESCAPED!"
     OSCLI "font Courier New, 24"
     PRINTTAB(9)"wins: "STR$(wins%)" losses: "STR$(losses%)

     COLOUR 3, 200,200,200: COLOUR 3
     OSCLI "font Courier New, 18"
     PRINT '"  Press any key to start, or <SPACE> to reset."
     REPEAT UNTIL INKEY(1) = -1

     g = GET
     IF 
g= 32 RUN
     WAIT 
100
     ENDPROC



     
DEFFN_canMove( m%(), x%, y% )
     REM check for a path or slime
     
IF m%(x%,y%) = 1 OR m%(x%,y%) = 2 THEN
       
=TRUE
     ELSE
       
=FALSE
     ENDIF


     
DEFFN_showIntro
     LOCAL g$
     OSCLI "refresh on":OSCLI "refresh"
     COLOUR 1, 0,0,0 : COLOUR 129 : CLS
     COLOUR 
2, 200,200,200: COLOUR 2
     OSCLI "font Courier New, 18"
     PRINTTAB(7,1)"Superdecade Games proudly presents..."
     OSCLI "font Courier New, 60b"
     COLOUR 3, 0, 240, 0: COLOUR 3
     PRINTTAB(1,1)"UH OH, SLIME!"
     COLOUR 2, 200,200,200: COLOUR 2

     OSCLI "font Courier New, 18"
     PRINT "       Use the cursor keys to escape from"
     PRINT "       the maze before the slime gets you." '
     OSCLI "font Courier New, 24b"
     PRINT "         (1) Don't hurt me!"
     PRINT "         (2) Novice"
     PRINT "         (3) Tricky"
     PRINT "         (4) Expert"
     PRINT "         (5) Impossible?"
     OSCLI "font Courier New, 18"
     PRINT'"          www.superdecade.blogspot.com"

     REPEAT
       
g$ = GET$
     UNTIL 
g$ = "1" OR g$="2" OR g$="3" OR g$="4" OR g$="5"

     = g$


     DEFPROC_createMaze( m%(), RETURN _entrance% )
     LOCAL x%, y%
     LOCAL mazeCounter%
     REM create one empty space
     REM somewhere in the grid

     
x% = RND(MAZE_WIDTH%-2)
     y% = RND(MAZE_HEIGHT%-2)
     m%(x%,y%) = 1 : REM set to path

     
REPEAT
       
x% = RND(MAZE_WIDTH%-2)
       y% = RND(MAZE_HEIGHT%-2)

       REM look around this space and
       REM create a path if it links
       REM to only one other space

       
IF m%(x%,y%+1)+m%(x%,y%-1)+m%(x%-1,y%)+m%(x%+1, y%) = 1 THEN
         
m%(x%,y%) = 1 : REM set to path
       
ENDIF

       
REM increment the maze pointer
       
mazeCounter% += 1

     UNTIL mazeCounter% = MAZE_COUNTER_LIMIT%

     REM place an exit on the top row
     
IF FN_placeExit( m%(), MAZE_HEIGHT%-1, MAZE_HEIGHT%-2, -1)

     REM place an exit on the bottom row
     
_entrance% = FN_placeExit( m%(), 0, 1, 1 )

     REM make one slime at entrance
     
m%(_entrance%, 0 ) = 2
     ENDPROC


     
DEFFN_placeExit( m%(), placeRow%, checkRow%, dir% )
     REM looks through the row for the first opportunity to
     REM place an exit that joins up with existing path
     REM dir -1 = check from right hand side
     REM dir  1 = check from left hand side
     REM returns the x position of the entrance/exit found
     
LOCAL x%
     LOCAL found%
     IF dir% = -1 THEN x% = MAZE_WIDTH%-1
     WHILE NOTfound% AND x%<MAZE_WIDTH% AND x%>-1
       IF m%(x%, checkRow% ) = 1 THEN
         
found% = TRUE
         
m%(x%, placeRow%) = 1 : REM place exit
       
ELSE
         
x% += dir%
       ENDIF
     ENDWHILE
     
= x%



     DEFPROC_drawMaze( m%() )
     REM show the maze
     REM 0 - wall
     REM 1 - path
     REM 2 - slime
     
LOCAL x%, y%
     COLOUR 2, 180,180,180: COLOUR 130 : CLS
     COLOUR 
1, 100,100,100 : GCOL 0, 1
     COLOUR 3, 0,240,0 : GCOL 0, 3
     :
     OSCLI "refresh off"
     FOR x% = 0 TO MAZE_WIDTH%-1
       FOR y% = 0 TO MAZE_HEIGHT% -1
         IF m%(x%,y%)= 0 THEN
           GCOL 
0, 1
           RECTANGLE FILL x%*CELL_WIDTH%,  y%*CELL_WIDTH%, CELL_WIDTH%, CELL_WIDTH%
         ENDIF
         IF 
m%(x%,y%)= 2 THEN
           GCOL 
0, 3
           RECTANGLE FILL x%*CELL_WIDTH%,  y%*CELL_WIDTH%, CELL_WIDTH%, CELL_WIDTH%
         ENDIF

       NEXT
     NEXT
     OSCLI 
"refresh"
     ENDPROC


     
DEFPROC_growSlime( m%() )
     REM if there is a path next to some slime, then there is a chance
     REM that slime will grow there
     
LOCAL slime%()
     DIM slime%( MAZE_WIDTH%-1, MAZE_HEIGHT%-1)
     REM check for each clear space next to a slime
     
FOR x% = 0 TO MAZE_WIDTH%-1
       FOR y% = 0 TO MAZE_HEIGHT% -1
         IF m%(x%,y%) = 2 THEN
           
REM found slime, check next door
           
IF x%-1 >= 0 THEN
             IF 
m%(x%-1,y%) = 1 THEN
               IF RND
(SLIME_CHANCE%) = SLIME_CHANCE% slime%(x%-1,y%) = 2
             ENDIF
           ENDIF
           IF 
x%+1 <= MAZE_WIDTH%-1 THEN
             IF 
m%(x%+1,y%) = 1 THEN
               IF RND
(SLIME_CHANCE%) = SLIME_CHANCE% slime%(x%+1,y%) = 2
             ENDIF
           ENDIF
           IF 
y%-1 >= 0 THEN
             IF 
m%(x%,y%-1) = 1 THEN
               IF RND
(SLIME_CHANCE%) = SLIME_CHANCE%  slime%(x%,y%-1) = 2
             ENDIF
           ENDIF
           IF 
y%+1 <= MAZE_HEIGHT%-1 THEN
             IF 
m%(x%,y%+1) = 1 THEN
               IF RND
(SLIME_CHANCE%) = SLIME_CHANCE%  slime%(x%,y%+1) = 2
             ENDIF
           ENDIF

         ENDIF
       NEXT
     NEXT
     FOR 
x% = 0 TO MAZE_WIDTH%-1
       FOR y% = 0 TO MAZE_HEIGHT% -1
         IF slime%(x%,y%) = 2 m%(x%,y%) = 2
       NEXT
     NEXT

     ENDPROC


     
DEFPROC_drawPlayer( x%, y% )
     REM show player's position as a red circle
     
OSCLI "refresh off"
     COLOUR 2, 250,0,0 : GCOL 0, 2
     CIRCLE FILL x%*CELL_WIDTH%+CELL_WIDTH% DIV 2,  y%*CELL_WIDTH%+CELL_WIDTH% DIV 2, CELL_WIDTH% DIV 2
     OSCLI "refresh"
     ENDPROC


     
DEFPROC_clearMaze( m%() )
     REM remove all data from the maze array
     
LOCAL x%, y%
     FOR x% = 0 TO MAZE_WIDTH%-1
       FOR y% = 0 TO MAZE_HEIGHT% -1
         m%(x%, y%) = 0
       NEXT
     NEXT
     ENDPROC


     
DEF PROC_preventResize
     REM prevent user resizing window
     
PRIVATE ws%
     SYS "GetWindowLong", @hwnd%, -16 TO ws%
     REM prevent user maximising window
     
SYS "SetWindowLong", @hwnd%, -16, ws% AND NOT &50000
     ENDPROC


#programming #randommaze #slime