Random Walk 3 - snakes!!

Remember the old Nokia game "SNAKE"?  Well, I decided to make a snake-like program in BB4W for today's random walk.  The program produces a number of snakes on the screen which then move randomly around.  Yes, you can have more than one snake.  Yes, they don't walk off the edge (that bit was quite tricky which is why this program took over an hour to code).  The snakes are different random colours, with the strongest colours indicated the heads.  Oh, and two other rules: snakes CAN move over each other, and themselves, but they cannot turn immediately back on themselves.

Enjoy!

 Indiana: There's a big snake in the plane, Jock! Jock: Oh, that's just my pet snake Reggie. Indiana: I hate snakes, Jock! I hate 'em! Jock: Come on! Show a little backbone, will ya!

REM Snake Walk 1
REM T Street
REM 2014-11-12

MODE 10  : OFF

SCREEN_WIDTH% = 1440
SCREEN_HEIGHT% = 1152

REM snake parameters

SNAKE_RADIUS% = 16 : REM size of the segments

SEGMENTS% = 20 : REM don't change to larger than this

REM create each snake

DIM snake1{ x%(SEGMENTS%-1), y%(SEGMENTS%-1),  head%, tail%, dir%, red%, green% }
DIM snake2{} = snake1{}
DIM snake3{} = snake1{}
DIM snake4{} = snake1{}
DIM snake5{} = snake1{}

REM setup the initial conditions for the snake

PROC_initialSnake( snake1{} )
PROC_initialSnake( snake2{} )
PROC_initialSnake( snake3{} )
PROC_initialSnake( snake4{} )
PROC_initialSnake( snake5{} )

REM main loop

REPEAT

*refresh off
PROC_drawSnake( snake1{} )
PROC_drawSnake( snake2{})
PROC_drawSnake( snake3{})
PROC_drawSnake( snake4{})
PROC_drawSnake( snake5{})
*refresh on

PROC_moveSnake( snake1{} )
PROC_moveSnake( snake2{} )
PROC_moveSnake( snake3{} )
PROC_moveSnake( snake4{} )
PROC_moveSnake( snake5{} )

WAIT 5 : REM wait a 'mo

CLS

UNTIL FALSE

DEFPROC_initialSnake( this{} )
LOCAL i%
REM intial position of snake

FOR i% = 0 TO SEGMENTS%-1
this.x%(i%) = i% + 8
this.y%(i%) = 12
NEXT

this.tail% = 0
this.dir% = RND(4) : REM initial direction

this.red% = RND(255-SEGMENTS%*6)   : REM colour of snake

this.green% = RND(255-SEGMENTS%*6) : REM colour of snake

ENDPROC

DEFPROC_drawSnake( this{} )
REM plots one snake on the screen

LOCAL colCycle%
LOCAL i%
LOCAL ok%
WHILE NOTok%
COLOUR 2, this.red%+colCycle%*6, this.green%+colCycle%*6, 0
GCOL 0,2
colCycle% +=1
PROC_circle( this.x%(i%), this.y%(i%) )
i% -= 1
IF i% <0 THEN i% = SEGMENTS%-1
IF i% = this.tail% THEN

ok% = TRUE
PROC
_circle( this.x%(i%), this.y%(i%) )
ENDIF
ENDWHILE
ENDPROC

DEFPROC_moveSnake( this{} )
LOCAL dir%, ok%
LOCAL checkx%, checky%

ENDIF

newTail% = this.tail% + 1
IF newTail% =SEGMENTS% THEN

newTail% = 0
ENDIF

REPEAT

ok% = TRUE

REM check snake is not going back on itself

REPEAT

dir% = RND(4)
UNTIL FN_dirOk(dir%, this.dir% )

REM check that snake will not move off the screen

CASE dir% OF
WHEN
1
WHEN 2
WHEN 3
WHEN 4
ENDCASE

IF
dir% = 1 THEN
IF

ok% = FALSE
ENDIF
ENDIF
IF
dir% = 2 THEN
IF

ok% = FALSE
ENDIF
ENDIF
IF
dir% = 3 THEN
IF

ok% = FALSE
ENDIF
ENDIF
IF
dir% = 4 THEN
IF

ok% = FALSE
ENDIF
ENDIF

UNTIL
ok%

REM snake has made a valid random move

CASE dir% OF
WHEN
1
WHEN 2

WHEN 3

WHEN 4

ENDCASE

this.tail% = newTail%
this.dir% = dir%
ENDPROC

DEFFN_dirOk( direction%, current% )
REM check snake not moving back on itself

IF ABS(direction%-current%) = 1 AND direction%+current% <> 5 THEN

FALSE
ELSE

TRUE
ENDIF

DEFPROC_circle( x%, y% )