DECLARE SUB Preview ()
DECLARE SUB Box (leftSide%, Top%, rside%, Bottom%)
DECLARE SUB BarStatus (Status AS ANY)
DECLARE SUB Capture (leftSide%, Top%, rside%, Bottom%)
DECLARE SUB CustomSpeed ()
DECLARE SUB Delay (sec!)
DECLARE SUB DetectBlock (Col%, Row%, Move%)
DECLARE SUB DrawBorder ()
DECLARE SUB FlashThePort ()
DECLARE SUB gPrint (Row%, Col%, Text$, Style%)
DECLARE SUB HowToPlay ()
DECLARE SUB Image (Row%, Col%, Image%)
DECLARE SUB Intro ()
DECLARE SUB Level (Status AS ANY)
DECLARE SUB LoadImages ()
DECLARE SUB Main ()
DECLARE SUB MainMenu (quit%)
DECLARE SUB NewImage (Img%)
DECLARE SUB Replace ()
DECLARE SUB ResetSnake (Body() AS ANY, Ground() AS INTEGER)
DECLARE SUB SpinThePill ()
DECLARE SUB TextBox (Row%, Col%, Text$)
DECLARE FUNCTION GetKey$ ()
DECLARE FUNCTION HitPill% (Col%, Row%)
DECLARE FUNCTION ImageOn% (x%, y%)
DECLARE FUNCTION Solid% (y%, x%)

DEFINT A-Z
RANDOMIZE TIMER
SCREEN 8

TYPE StatusType
    Score AS INTEGER
    Lives AS INTEGER
    Level AS INTEGER
    Length AS INTEGER
    Continue AS INTEGER
END TYPE
TYPE FruitType
    Total AS INTEGER
    Level AS INTEGER
    Apples AS INTEGER
    Pears AS INTEGER
END TYPE
TYPE OptionsType
    Slither AS SINGLE
    Home AS INTEGER
    PowerHead AS INTEGER
    Growth AS INTEGER
END TYPE
TYPE GenType
    Col AS INTEGER
    Row AS INTEGER
    Active AS INTEGER
END TYPE

CONST UP = 72, DOWN = 80, LEFT = 75, RIGHT = 77
CONST ENTER = 13, ESC = 27, SPACE = 32

CONST PI! = 3.14159, Img = 16
CONST TRUE = -1, FALSE = 0

CONST NULL = 1, SNAKE = 17, APPLE = 35, PEAR = 51, BLOCK = 67
CONST BRICK = 83, PORTAL = 99, HOLESHUT = 131, HOLEOPEN = 147
CONST BLOCKHOLE = 163, BRICKHOLE = 181, STEROID = 197

CONST FAST = 90000!, SLOW = 310000!
CONST optKEYS = 0, optSELF = 1, optCENTER = 2, optHOMELESS = 3, optSHELTERED = 4
CONST optHARDHAT = 5, optBALLCAP = 6, optSTEROIDS = 7, optAPPLESAUCE = 8

DIM TextTemp(1 TO 2000) AS INTEGER
DIM SHARED Grid(1 TO 80, 1 TO 50) AS INTEGER
DIM SHARED PortHole(1 TO 2) AS GenType
DIM SHARED Home AS GenType
DIM SHARED Pill AS GenType
DIM SHARED Port AS GenType
DIM SHARED AlphaImage(1 TO 31 * Img) AS INTEGER
DIM SHARED NumberImage(1 TO 10 * Img) AS INTEGER
DIM SHARED Images(1 TO 16 * Img) AS INTEGER
DIM SHARED Fruit AS FruitType
DIM SHARED OptionsData AS OptionsType
DIM SHARED Required AS INTEGER
DIM SHARED Move AS INTEGER
DIM SHARED StartLevel AS INTEGER
DIM Caught AS GenType

'   default options
OptionsData.Slither = SLOW
OptionsData.Home = optSHELTERED
OptionsData.PowerHead = optBALLCAP
OptionsData.Growth = optAPPLESAUCE

CALL LoadImages
CALL Intro
CALL MainMenu(quit%)
DO UNTIL quit%
   CALL Main
   CALL Intro
   CALL MainMenu(quit%)
   DIM tf AS FruitType: Fruit = tf
LOOP

FruitData:
DATA 2,2,2,2,0,0,0,0,0,0,2,2,4,4,0,0,4,4,4,4,4,4,4,4,0,0,4,4,4,4,0,0

WallData:
DATA 7,8,8,7,7,7,7,7,8,8,8,8,8,8,8,8,7,7,7,7,8,8,7,7,7,7,7,7,8,8,7,7

PortalData:
DATA 1,1,1,1,1,1,1,1,1,1,3,3,3,3,1,1,1,1,3,3,3,3,1,1,1,1,1,1,1,1,1,1
DATA 3,3,3,3,3,3,3,3,3,3,1,1,1,1,3,3,3,3,1,1,1,1,3,3,3,3,3,3,3,3,3,3

HoleData:
DATA 0,7,7,7,15,15,15,0,7,7,7,8,8,8,7,15,7,7,7,8,8,7,7,7,0,7,7,7,7,7,7,0

HomeData:
DATA 0,0,6,6,6,6,0,0,6,6,8,8,8,8,6,6,6,6,7,7,8,8,6,6,6,6,7,7,8,8,6,6

SteroidData:
DATA 0,0,15,15,3,3,0,0,15,15,15,15,3,3,3,3,15,15,15,15,3,3,3,3,0,0,15,15,3,3,0,0
DATA 0,0,15,3,3,15,0,0,15,15,3,3,3,3,15,15,15,15,3,3,3,3,15,15,0,0,15,3,3,15,0,0
DATA 0,0,3,3,15,15,0,0,3,3,3,3,15,15,15,15,3,3,3,3,15,15,15,15,0,0,3,3,15,15,0,0
DATA 0,0,3,15,15,3,0,0,3,3,15,15,15,15,3,3,3,3,15,15,15,15,3,3,0,0,3,15,15,3,0,0

Zero:
DATA 0,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0
DATA 0,1,1,1,0,0,1,1,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0
DATA 0,1,1,1,0,0,1,1,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0
DATA 1,1,1,1,0,0,0,0,0,1,1,0,0,1,1,1,0,0,0,0,0,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0
DATA 1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0
DATA 1,1,1,1,0,0,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0
DATA 0,1,1,1,0,0,1,1,0,0,0,0,1,1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0
DATA 1,1,1,1,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0
DATA 0,1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0
DATA 0,1,1,1,1,0,1,1,0,1,1,0,0,1,1,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0

A:
DATA 0,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,0,0,0,0,0,0
DATA 1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0
DATA 0,1,1,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0
DATA 1,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0
DATA 1,1,1,1,1,0,1,1,0,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0
DATA 1,1,1,1,1,0,1,1,0,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0
DATA 0,1,1,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0
DATA 1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,0,0,0,0,0,0
DATA 0,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0
DATA 0,1,1,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0
DATA 1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,0,0,0,0,0,0,0
DATA 1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0
DATA 1,0,0,0,1,0,1,1,0,1,1,0,1,1,1,1,1,0,1,0,1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0
DATA 1,0,0,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,0,1,1,0,0,0,0,0,0,0
DATA 0,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0
DATA 1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0
DATA 0,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,0,0,0
DATA 1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,0,0,0,0,0,0,0
DATA 0,1,1,1,1,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0
DATA 0,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0
DATA 1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0
DATA 1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0
DATA 1,0,0,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,1,1,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0
DATA 1,1,0,1,1,0,1,1,0,1,1,0,0,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,0,0,0,0,0,0,0
DATA 1,1,0,1,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0
DATA 1,1,1,1,1,0,0,0,0,1,1,0,0,1,1,1,0,0,1,1,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0
DATA 0,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0

OptsData:
DATA "    start    ", "start the action"
DATA "   options   ", "set game options"
DATA " how to play ", "describes how to play"
DATA "   preview   ", "preview all the levels"
DATA "    exit     ", "exits the game"

DATA "  slithers  ", "set the speed of the snake"
DATA "    home    ", "set where the snakes hole is"
DATA " power head ", "set the strength of the snake"
DATA "   growth   ", "set how fast the snake grows"
DATA "   return   ", "return to main menu"

DATA "    fast    ", "the snake is energized"
DATA "    slow    ", "it just woke up"
DATA "   custom   ", "set the speed according to your computer"

DATA "  sheltered ", "finds its way home everyday"
DATA "  homeless  ", "finds a new home everyday"

DATA "  ball cap  ", "it climbs over walls"
DATA "  hard hat  ", "the snake breaks through walls"

DATA " applesauce ", "the snake grows slow"
DATA "  steroids  ", "power pills, be careful"


HowTo:

' Tags:
'  <tb> = tab
'  <ap> = apple
'  <pr> = pear
'  <st> = steroid
'  <hc> = closed hole
'  <ho> = open hole
'  <bl> = block wall
'  <br> = brick wall
'  <rh> = hole in brick
'  <lh> = hole in block
'  <lf> = line feed
'  <ed> = end of data
'  <cr> = carriage return
'  <sn> = snake
'  <ct> = center

DATA "<tb>snake <sn> is another version of the classic nibbles game. use the arrow"
DATA "<sp>keys to move the snake <sn> around the garden. use the space bar to pause and"
DATA "<sp>esc to stop the game and return to the main menu."
DATA "<tb>the garden snake <sn> must collect all 9 apples <ap> and 1 pear <pr> to go to the"
DATA "<sp>next level. when the snake <sn> first leaves its hole <ho>, it will close <hc> and"
DATA "<sp>not open <ho> until all 10 fruit are collected."
DATA "<tb>when the snake <sn> has a pear <pr>, it can go over block <bl> walls, but never"
DATA "<sp>brick <br> walls. when the snake <sn> goes over a block <bl> wall, it loses 1 pear <pr>."
DATA "<lf><lf><lf>"
DATA "<tb>the snake <sn> can go through the holes found in the bricks <rh> and blocks <lh>"
DATA "<sp>to move around the garden faster."
DATA "<tb>points are earned based on how long the snake <sn> is when it collects"
DATA "<sp>fruit <ap><pr>, goes over a wall <bl>, and through holes <rh><lh> in the walls. the
DATA "<sp>snake <sn> grows every time it collects a fruit <ap><pr> or a steroid pill <st>."
DATA "<tb>the snake <sn> will die if it hits itself <sn>, or a brick <br> wall."
DATA "<tb>a hidden portal <pt> will open that allows the snake <sn> to finish the level"
DATA "<sp>early if the snake <sn> has the right amount of points. but this usually only"
DATA "<sp>happens when the snake is running low on extra lives.<lf>"
DATA "<ct>Press any key to return to main menu."
DATA "<ed>"

'   shows the game status on left side of screen
SUB BarStatus (Status AS StatusType)

sc$ = LTRIM$(STR$(Status.Level))
CALL gPrint(7, 2, SPACE$(4 - LEN(sc$)) + sc$, TRUE)

sc$ = LTRIM$(STR$(Status.Score))
CALL gPrint(7, 4, SPACE$(4 - LEN(sc$)) + sc$, TRUE)

sc$ = LTRIM$(STR$(Fruit.Apples))
CALL gPrint(7, 6, SPACE$(4 - LEN(sc$)) + sc$, TRUE)

sc$ = LTRIM$(STR$(Fruit.Pears))
CALL gPrint(7, 8, SPACE$(4 - LEN(sc$)) + sc$, TRUE)

sc$ = LTRIM$(STR$(Status.Lives))
CALL gPrint(7, 10, SPACE$(4 - LEN(sc$)) + sc$, TRUE)

sc$ = LTRIM$(STR$(Status.Length))
CALL gPrint(7, 12, SPACE$(4 - LEN(sc$)) + sc$, TRUE)

END SUB

'  draws a graphic blue box with white border and round corners
SUB Box (leftSide%, Top%, rside%, Bottom%)

MaxH = (rside% - leftSide%) * 8
MaxV = (Bottom% - Top% + 1) * 8
TSide = (Top * 8) - 8
lSide = (leftSide * 8) - 8

CALL Capture(leftSide, Top, rside, Bottom)

'   TopLine
LINE (lSide - 2, TSide - 4)-(lSide + MaxH, TSide - 4), 15

'   BottomLine
LINE (lSide - 2, TSide + MaxV)-(lSide + MaxH, TSide + MaxV), 15

'   LeftLine
LINE (lSide - 6, TSide - 2)-(lSide - 6, TSide + MaxV - 3), 15

'   RightLine
LINE (lSide + MaxH + 4, TSide - 2)-(lSide + MaxH + 4, TSide + MaxV - 3), 15

'   TopLeft
CIRCLE (lSide - 2, TSide - 2), 4, 15, PI / 2, PI

'   BottomLeft
CIRCLE (lSide - 2, TSide + MaxV - 2), 4, 15, PI, PI * 1.5

'   TopRight
CIRCLE (lSide + MaxH, TSide - 2), 4, 15, 0, PI / 2

'   BottomRight
CIRCLE (lSide + MaxH, TSide + MaxV - 2), 4, 15, PI * 1.5, 0

PAINT (lSide + 1, TSide + 1), 1, 15

END SUB

'  stores a specific portion of the graphic screen in memory
SUB Capture (leftSide%, Top%, rside%, Bottom%)

SHARED TextTemp() AS INTEGER
SHARED Caught AS GenType

MaxH = (rside% - leftSide%) * 8
MaxV = (Bottom% - Top% + 1) * 8
TSide = (Top * 8) - 8
lSide = (leftSide * 8) - 8

GET (lSide - 6, TSide - 4)-(lSide + MaxH + 4, TSide + MaxV + 2), TextTemp
Caught.Col = lSide - 6
Caught.Row = TSide - 4

END SUB

'  allows the player to customize the delay speed
SUB CustomSpeed

DIM BlueBox(1 TO 32) AS INTEGER
DIM TempSpeed AS SINGLE

LINE (10, 10)-STEP(7, 7), 1, BF
GET (10, 10)-STEP(7, 7), BlueBox(1)
LINE (10, 10)-STEP(7, 7), 0, BF

LINE (150, 100)-(500, 190), 0, BF

CALL gPrint(30, 17, "left/right = select", TRUE)
CALL gPrint(30, 18, "   up/down = change", TRUE)

CALL gPrint(25, 20, "a bigger number means the snake", TRUE)
CALL gPrint(25, 21, "will move slower. a smaller", TRUE)
CALL gPrint(25, 22, "number will move the snake faster.", TRUE)

del$ = LTRIM$(STR$(OptionsData.Slither))
IF LEN(del$) < 6 THEN del$ = STRING$(6 - LEN(del$), "0") + del$
CALL Box(31, 14, 46, 14)
CALL gPrint(31, 14, "Speed = " + del$, FALSE)

maxlen = 6
digit = 6
Done = FALSE

Pill.Col = 50
Pill.Row = 27
Pill.Active = TRUE
TempSpeed = OptionsData.Slither
DO
  
   GOSUB numhigh
   DO
      kb$ = INKEY$
      SpinThePill
      Delay TempSpeed
   LOOP WHILE kb$ = ""
  
   GOSUB numlow
   SELECT CASE RIGHT$(kb$, 1)
      CASE CHR$(UP)
         value = VAL(MID$(del$, digit%, 1)) + 1
         IF value > 9 THEN value = 9
         MID$(del$, digit%, 1) = LTRIM$(STR$(value))
      CASE CHR$(DOWN)
         value = VAL(MID$(del$, digit%, 1)) - 1
         IF value < 0 THEN value = 0
         MID$(del$, digit%, 1) = LTRIM$(STR$(value))
      CASE CHR$(LEFT)
         digit = digit - 1
         IF digit = 0 THEN digit = 1
      CASE CHR$(RIGHT)
         digit = digit + 1
         IF digit = 7 THEN digit = 6
      CASE CHR$(ENTER), CHR$(SPACE)
         Done = TRUE
         OptionsData.Slither = TempSpeed
      CASE CHR$(ESC)
         Done = TRUE
   END SELECT
   TempSpeed = VAL(del$)
   IF TempSpeed = 0 THEN TempSpeed = FAST
LOOP UNTIL Done

EXIT SUB

numhigh:
   PUT ((38 + digit%) * 8 - 8, 14 * 8 - 9), BlueBox(1), XOR
   CALL gPrint(38 + digit%, 14, MID$(del$, digit%, 1), TRUE)
RETURN

numlow:
   PUT ((38 + digit%) * 8 - 8, 14 * 8 - 9), BlueBox(1), PSET
   CALL gPrint(38 + digit%, 14, MID$(del$, digit%, 1), FALSE)
RETURN

END SUB

'   uses a single precision variable for the delay
SUB Delay (Count!)

FOR x! = 1 TO Count!: NEXT x!

END SUB

'  finds which way the snake should move after entering a hole
SUB DetectBlock (Col, Row, Move)

pass = FALSE
DO UNTIL pass
   SELECT CASE Move
       CASE UP
         Im = ImageOn(Col, Row - 1)
         IF Im = BLOCK OR Im = BRICK THEN Move = LEFT ELSE pass = TRUE
       CASE DOWN
         Im = ImageOn(Col, Row + 1)
         IF Im = BLOCK OR Im = BRICK THEN Move = RIGHT ELSE pass = TRUE
       CASE LEFT
         Im = ImageOn(Col - 1, Row)
         IF Im = BLOCK OR Im = BRICK THEN Move = DOWN ELSE pass = TRUE
       CASE RIGHT
         Im = ImageOn(Col + 1, Row)
         IF Im = BLOCK OR Im = BRICK THEN Move = UP ELSE pass = TRUE
   END SELECT
LOOP

END SUB

'   draws the screen border and status
SUB DrawBorder

ERASE Grid

FOR x = 11 TO 80
    CALL Image(x, 3, BRICK)
    CALL Image(x, 50, BRICK)
NEXT x

FOR x = 3 TO 50
    CALL Image(11, x, BRICK)
    CALL Image(80, x, BRICK)
NEXT x

CALL gPrint(1, 2, "Level=", FALSE)
CALL gPrint(1, 4, "Score=", FALSE)
CALL Image(3, 11, APPLE): CALL gPrint(6, 6, "=", FALSE)
CALL Image(3, 15, PEAR): CALL gPrint(6, 8, "=", FALSE)
CALL gPrint(1, 12, "Length=", FALSE)

CALL Image(2, 18, SNAKE)
CALL Image(3, 18, SNAKE)
CALL Image(4, 19, SNAKE)
CALL Image(3, 20, SNAKE)
CALL gPrint(6, 10, "=", FALSE)

END SUB

'  flashes the portal when opened
SUB FlashThePort STATIC

IF Port.Active THEN

   Flash = NOT Flash
   CALL Image(Port.Col, Port.Row, PORTAL - (16 * Flash))
END IF

END SUB

'   prints graphics letters/symbols and interprets tags
SUB gPrint (xCol, Row, Text$, OverWrite%)

Col = xCol
IF Col = optCENTER THEN Col = 40 - LEN(Text$) / 2
BaseH = (Col * 8) - 8
BaseV = (Row * 8) - 8

Text$ = UCASE$(Text$)
FOR x = 1 TO LEN(Text$)
    IF MID$(Text$, x, 1) = "<" THEN
         tag$ = MID$(Text$, x, 4)
         SELECT CASE LCASE$(tag$)
            CASE "<ap>"
               CALL Image(Col, Row * 2 - 1, APPLE)
            CASE "<pr>"
               CALL Image(Col, Row * 2 - 1, PEAR)
            CASE "<ho>"
               CALL Image(Col, Row * 2 - 1, HOLEOPEN)
            CASE "<hc>"
               CALL Image(Col, Row * 2 - 1, HOLESHUT)
            CASE "<bl>"
               CALL Image(Col, Row * 2 - 1, BLOCK)
            CASE "<br>"
               CALL Image(Col, Row * 2 - 1, BRICK)
            CASE "<rh>"
               CALL Image(Col, Row * 2 - 1, BRICKHOLE)
            CASE "<lh>"
               CALL Image(Col, Row * 2 - 1, BLOCKHOLE)
            CASE "<sn>"
               CALL Image(Col, Row * 2 - 1, SNAKE)
            CASE "<st>"
               Pill.Col = Col
               Pill.Row = Row * 2 - 1
               Pill.Active = TRUE
            CASE "<pt>"
               Port.Col = Col
               Port.Row = Row * 2 - 1
               Port.Active = TRUE
            CASE "<tb>"
               Col = 4
            CASE "<lf>"
               Row = Row + 1
            CASE "<ct>"
               Col = 40 - LEN(Text$) / 2
            CASE "<ed>"
               Text$ = "<ed>"
               EXIT FOR
            CASE "<sp>"
               Col = 2
         END SELECT
         x = x + 3
         Col = Col + 1
    ELSE
       ch = ASC(MID$(Text$, x, 1))
       BaseH = (Col * 8) - 8
       IF OverWrite% THEN
           SELECT CASE ch
               CASE 64 TO 91: PUT (BaseH, BaseV), AlphaImage((ch - 64) * Img - 15), PSET
               CASE 48 TO 57: PUT (BaseH, BaseV), NumberImage((ch - 47) * Img - 15), PSET
               CASE 61: PUT (BaseH, BaseV), AlphaImage(27 * Img - 15), PSET
               CASE 46: PUT (BaseH, BaseV), AlphaImage(28 * Img - 15), PSET
               CASE 44: PUT (BaseH, BaseV), AlphaImage(29 * Img - 15), PSET
               CASE 47: PUT (BaseH, BaseV), AlphaImage(30 * Img - 15), PSET
               CASE 32: PUT (BaseH, BaseV), AlphaImage(31 * Img - 15), PSET
           END SELECT
       ELSE
           SELECT CASE ch
               CASE 64 TO 91: PUT (BaseH, BaseV), AlphaImage((ch - 64) * Img - 15), XOR
               CASE 48 TO 57: PUT (BaseH, BaseV), NumberImage((ch - 47) * Img - 15), XOR
               CASE 61: PUT (BaseH, BaseV), AlphaImage(27 * Img - 15), XOR
               CASE 46: PUT (BaseH, BaseV), AlphaImage(28 * Img - 15), XOR
               CASE 44: PUT (BaseH, BaseV), AlphaImage(29 * Img - 15), XOR
               CASE 47: PUT (BaseH, BaseV), AlphaImage(30 * Img - 15), XOR
               CASE 32: PUT (BaseH, BaseV), AlphaImage(31 * Img - 15), XOR
           END SELECT
       END IF
       Col = Col + 1
    END IF
NEXT x

END SUB

'  finds if the snake picked up a pill
FUNCTION HitPill% (Col, Row)

HitPill% = FALSE
FOR x = 0 TO 3
   IF ImageOn(Col, Row) = STEROID + (x * Img) THEN
      HitPill% = STEROID + (x * Img)
      EXIT FOR
   END IF
NEXT x

END FUNCTION

'  tells how to play the game
SUB HowToPlay

LINE (8, 5)-(630, 75), 0, BF
LINE (8, 100)-(630, 180), 0, BF

Done = 0
Row = 2
RESTORE HowTo
DO
   READ Text$
           
   CALL gPrint(2, Row, Text$, TRUE)
   IF Text$ = "<ed>" THEN Done% = TRUE
   Row = Row + 1
LOOP UNTIL Done%

DO
   i$ = INKEY$
   SpinThePill
   FlashThePort
   Delay OptionsData.Slither
LOOP WHILE i$ = ""

LINE (8, 5)-(630, 75), 0, BF
LINE (8, 100)-(630, 190), 0, BF

END SUB

'   prints objects on the screen
SUB Image (Col, Row, Object)

IF Object < 1 THEN EXIT SUB
PUT (Col * 8 - 8, Row * 4 - 4), Images(Object), PSET
Grid(Col, Row) = Object
IF Object = STEROID THEN Pill.Active = TRUE
IF Object = PORTAL THEN Port.Active = TRUE

END SUB

'   finds an image at the specified point on the screen
FUNCTION ImageOn% (Col, Row)

ImageOn = Grid(Col, Row)
IF Grid(Col, Row) = 0 THEN ImageOn = NULL

END FUNCTION

'   intro screen
SUB Intro

CLS
CALL gPrint(1, 1, "SNAKE", TRUE)
FOR x = 0 TO 6
    FOR y = 0 TO 36
        pix = POINT(y, x)
        IF pix THEN
            CALL Image(y + 20, x + 20, BLOCK)
        END IF
    NEXT y
NEXT x
LINE (0, 0)-(45, 10), 0, BF

FOR x = 1 TO 80
   CALL Image(x, 1, BRICK)
   CALL Image(x, 50, BRICK)
NEXT x
FOR x = 1 TO 50
   CALL Image(1, x, BRICK)
   CALL Image(80, x, BRICK)
NEXT x

END SUB

'   changes the level
SUB Level (Status AS StatusType)

CLS
CALL DrawBorder

'  dimensions 80x50

SELECT CASE Status.Level
    CASE 1
        Home.Col = 20
        Home.Row = 20
        Move = RIGHT
        Required = 300

    CASE 2
        Home.Col = 20
        Home.Row = 20
        Move = RIGHT
        Required = 600
        FOR i = 30 TO 60
            CALL Image(i, 25, BLOCK)
            CALL Image(i, 26, BLOCK)
        NEXT i

    CASE 3
        Home.Col = 40
        Home.Row = 30
        Move = UP
        Required = 900
        FOR i = 10 TO 40
            CALL Image(30, i, BLOCK)
            CALL Image(60, i, BLOCK)
        NEXT i

    CASE 4
        Home.Col = 45
        Home.Row = 30
        Move = UP
        Required = 1200
        FOR i = 4 TO 30
            CALL Image(30, i, BLOCK)
            CALL Image(60, 53 - i, BLOCK)
        NEXT i
        FOR i = 12 TO 40
            CALL Image(i, 38, BLOCK)
            CALL Image(91 - i, 15, BLOCK)
        NEXT i

    CASE 5
        Home.Col = 40
        Home.Row = 40
        Move = UP
        Required = 1500
        FOR i = 13 TO 39
            CALL Image(31, i, BLOCK)
            CALL Image(59, i, BLOCK)
        NEXT i
        FOR i = 33 TO 57
            CALL Image(i, 11, BLOCK)
            CALL Image(i, 41, BLOCK)
        NEXT i

    CASE 6
        Home.Col = 20
        Home.Row = 25
        Move = RIGHT
        Required = 1800
        FOR i = 4 TO 49
            IF i > 30 OR i < 23 THEN
                CALL Image(20, i, BLOCK)
                CALL Image(30, i, BLOCK)
                CALL Image(40, i, BLOCK)
                CALL Image(50, i, BLOCK)
                CALL Image(60, i, BLOCK)
                CALL Image(70, i, BLOCK)
            END IF
        NEXT i

    CASE 7
        Home.Col = 20
        Home.Row = 20
        Move = RIGHT
        Required = 2100
        FOR i = 4 TO 49 STEP 2
            CALL Image(45, i, BLOCK)
        NEXT i

    CASE 8
        Home.Col = 16
        Home.Row = 14
        Move = DOWN
        Required = 2400
        FOR i = 10 TO 44
            CALL Image(i + 5, i, BLOCK)
            CALL Image(i + 32, i, BLOCK)
        NEXT i

    CASE 9
        Home.Col = 24
        Home.Row = 40
        Move = UP
        Required = 2700
        FOR i = 4 TO 40
            CALL Image(20, 53 - i, BLOCK)
            CALL Image(30, i, BLOCK)
            CALL Image(40, 53 - i, BLOCK)
            CALL Image(50, i, BLOCK)
            CALL Image(60, 53 - i, BLOCK)
            CALL Image(70, i, BLOCK)
        NEXT i
     
    CASE 10
        Home.Col = 15
        Home.Row = 15
        Move = DOWN
        Required = 3000
        FOR i = 4 TO 23
            FOR p = 3 TO 7 STEP 2
                CALL Image(10 * p, i, BLOCK)
            NEXT p
        NEXT i
        FOR i = 26 TO 49
            FOR p = 3 TO 7 STEP 2
                CALL Image(10 * p, i, BLOCK)
            NEXT p
        NEXT i
        FOR i = 10 TO 50 STEP 20
            FOR p = 1 TO 10
                CALL Image(i + p, 10, BLOCK)
                CALL Image(i + p + 10, 20, BLOCK)
                CALL Image(i + p, 30, BLOCK)
                CALL Image(i + p + 10, 40, BLOCK)
            NEXT p
        NEXT i
       
    CASE 11
        Home.Col = 30
        Home.Row = 20
        Move = UP
        Required = 3300
        FOR i = 16 TO 64 STEP 16
            FOR p = 1 TO 7
                CALL Image(i + p, 7, BLOCK)
                CALL Image(i + p, 22, BLOCK)
                CALL Image(i + p, 30, BLOCK)
                CALL Image(i + p, 45, BLOCK)
            NEXT p
            FOR p = 8 TO 21
                CALL Image(i + 4, p, BLOCK)
                CALL Image(i + 4, p + 23, BLOCK)
            NEXT p
        NEXT i
   
    CASE 12
        Home.Col = 60
        Home.Row = 44
        Move = RIGHT
        Required = 3600
        FOR x = 16 TO 72 STEP 8
           FOR y = 6 TO 50 STEP 5
              CALL Image(x, y, BLOCK)
              CALL Image(x + 1, y, BLOCK)
              CALL Image(x + 1, y + 1, BLOCK)
           NEXT y
        NEXT x

    CASE 13
        Home.Col = 76
        Home.Row = 44
        Move = UP
        Required = 3900
        FOR Z = 0 TO 20 STEP 20
           FOR p = 0 TO 50 STEP 8
              FOR x = 18 TO 19
                 FOR y = 8 TO 12
                    CALL Image(x + p, y + Z, BLOCK)
                    CALL Image(x + p + 2, y + 4 + Z, BLOCK)
                    CALL Image(x + p + 4, y + 8 + Z, BLOCK)
                    CALL Image(x + p + 6, y + 12 + Z, BLOCK)
                 NEXT y
              NEXT x
           NEXT p
        NEXT Z
   
    CASE 14
        Home.Col = 20
        Home.Row = 20
        Move = RIGHT
        Required = 4200
        FOR i = 6 TO 49 STEP 3
            FOR p = 14 TO 72 STEP 9
                FOR x = 1 TO 7
                   CALL Image(p + x, i, BLOCK)
                NEXT x
            NEXT p
        NEXT i

    CASE 15
        Home.Col = 25
        Home.Row = 40
        Move = UP
        Required = 4500
        FOR i = 4 TO 49 STEP 2
            CALL Image(20, i + 1, BLOCK)
            CALL Image(30, i, BLOCK)
            CALL Image(40, i + 1, BLOCK)
            CALL Image(50, i, BLOCK)
            CALL Image(60, i + 1, BLOCK)
            CALL Image(70, i, BLOCK)
        NEXT i

END SELECT

IF Options.Growth = optSTEROIDS THEN Required = Required + 50

CALL NewImage(APPLE)
CALL NewImage(BRICKHOLE)
CALL BarStatus(Status)

del$ = STR$(Status.Level)
CALL Box(40, 12, 45 + LEN(del$), 12)
CALL gPrint(40, 12, "Level" + del$, FALSE)

END SUB

'   loads the graphics images from data
SUB LoadImages

CLS

'   blank square
LINE (0, 0)-(7, 3), 0, BF
GET (0, 0)-(7, 3), Images(NULL)
imgs = imgs + 1

'   Snake
LINE (0, 0)-(7, 3), 2, BF
GET (0, 0)-(7, 3), Images(SNAKE)
imgs = imgs + 1

'   Fruit
RESTORE FruitData
FOR x = 0 TO 3
    FOR y = 0 TO 7
        READ pix
        pix2 = pix
        IF pix = 4 THEN pix2 = 14
        PSET (y + 8, x), pix
        PSET (y + 16, x), pix2
    NEXT y
NEXT x
GET (8, 0)-(15, 3), Images(APPLE)
GET (16, 0)-(23, 3), Images(PEAR)
imgs = imgs + 2

'   Wall Image
RESTORE WallData
FOR x = 0 TO 3
    FOR y = 0 TO 7
        READ pix
        pix2 = pix
        IF pix2 = 7 THEN pix2 = 12
        PSET (y + 24, x), pix
        PSET (y + 32, x), pix2
    NEXT y
NEXT x
GET (24, 0)-(31, 3), Images(BLOCK)
GET (32, 0)-(39, 3), Images(BRICK)
imgs = imgs + 2

'   PORTAL Image
RESTORE PortalData
FOR p = 0 TO 1
   FOR x = 0 TO 3
       FOR y = 0 TO 7
           READ pix
           PSET (y + 32 + (p * 8), x + 4), pix
       NEXT y
   NEXT x
   GET (32 + (p * 8), 4)-STEP(7, 3), Images(PORTAL + (p * Img))
   imgs = imgs + 1
NEXT p

'   Home Image
RESTORE HomeData
FOR x = 0 TO 3
    FOR y = 0 TO 7
        READ pix
        pix2 = pix
        IF pix = 7 THEN pix2 = 0
        PSET (y + 48, x), pix
        PSET (y + 56, x), pix2
    NEXT y
NEXT x
GET (48, 0)-(55, 3), Images(HOLESHUT)
GET (56, 0)-(63, 3), Images(HOLEOPEN)
imgs = imgs + 2

'   Block holes Image
RESTORE HoleData
FOR x = 0 TO 3
    FOR y = 0 TO 7
        READ pix
        pix2 = pix
        IF pix = 7 THEN pix2 = 4
        PSET (y + 64, x), pix
        PSET (y + 72, x), pix2
    NEXT y
NEXT x
GET (64, 0)-(71, 3), Images(BLOCKHOLE)
GET (72, 0)-(79, 3), Images(BRICKHOLE)
imgs = imgs + 2

'   Steroid Image
RESTORE SteroidData
FOR p = 0 TO 3
   FOR x = 0 TO 3
       FOR y = 0 TO 7
           READ pix
           PSET (p * 8 + y, x + 4), pix
       NEXT y
   NEXT x
   GET (p * 8, 4)-STEP(7, 3), Images(STEROID + (Img * p))
   imgs = imgs + 1
NEXT p

'   Numbers
RESTORE Zero
FOR p = 1 TO 10
    FOR x = 0 TO 5
        FOR y = 0 TO 5
            READ pix
            IF pix = 1 THEN pix = 15
            PSET (p * 6 + 74 + y, x), pix
        NEXT y
    NEXT x
    GET (p * 6 + 74, 0)-STEP(5, 5), NumberImage(p * Img - 15)
NEXT p

'   AlphaImage
RESTORE A
FOR p = 1 TO 30
    FOR x = 0 TO 5
        FOR y = 0 TO 5
            READ pix
            IF pix = 1 THEN pix = 15
            PSET (p * 6 + y + 134, x), pix
        NEXT y
    NEXT x
    GET (p * 6 + 134, 0)-STEP(5, 5), AlphaImage(p * Img - 15)
NEXT p
GET (31 * 6 + 134, 0)-STEP(5, 5), AlphaImage(31 * Img - 15)

'PRINT : PRINT "Images: "; imgs;
'END
CLS

END SUB

'   main routine
SUB Main

DIM Body(1 TO 200) AS GenType
DIM Ground(1 TO 200) AS INTEGER
DIM Status AS StatusType

Status.Level = 1
Status.Lives = 4
Status.Continue = 1
Next.Continue = 250

DO
   
    CALL Level(Status)
    i$ = INPUT$(1)
    Replace

    CALL ResetSnake(Body(), Ground())
    Assign = 0
    Fruit.Level = 0
    Status.Length = 5
    Col = Home.Col
    Row = Home.Row
    CALL Image(Col, Row, HOLEOPEN)
    Undo = FALSE
    Died = FALSE
    Done = FALSE
    HoleIn = FALSE
    CALL BarStatus(Status)
    Port.Active = FALSE
    Pill.Active = FALSE

    DO
       
        '   increment Assign counter
        Assign = Assign + 1
        IF Assign > Status.Length THEN
            Undo = TRUE
            Assign = 1
            IF Fruit.Level < 10 THEN
                IF OptionsData.Home = optHOMELESS THEN
                    CALL Image(Home.Col, Home.Row, NULL)
                ELSEIF ImageOn(Home.Col, Home.Row) <> SNAKE THEN
                    CALL Image(Home.Col, Home.Row, HOLESHUT)
                END IF
            END IF
        END IF

        '   erase tail
        IF Undo THEN CALL Image(Body(Assign).Col, Body(Assign).Row, Ground(Assign))

        '   move Assign
        SELECT CASE Move
            CASE UP: Row = Row - 1
            CASE DOWN: Row = Row + 1
            CASE LEFT: Col = Col - 1
            CASE RIGHT: Col = Col + 1
        END SELECT

        '   new steriod pill?
        IF OptionsData.Growth = optSTEROIDS AND Pill.Active = FALSE THEN
            chance = INT(RND * 40) + 1
            IF chance = 1 THEN CALL NewImage(STEROID)
        END IF

        '   spin pill?
        IF Pill.Active THEN SpinThePill

        '   flash portal?
        IF Port.Active THEN FlashThePort

        '   check for contact
        SELECT CASE ImageOn(Col, Row)
           
            CASE BLOCK
                IF Fruit.Pears > 0 THEN
                    Fruit.Pears = Fruit.Pears - 1
                    Status.Score = Status.Score + Status.Length * 2
                ELSE
                    Died = TRUE
                END IF
                IF OptionsData.PowerHead = optHARDHAT THEN
                    CALL Image(Col, Row, NULL)
                    Status.Score = Status.Score - 10
                END IF
                CALL BarStatus(Status)
           
            CASE BRICK, SNAKE
                Died = TRUE

            CASE HitPill(Col, Row)
                CALL Image(Col, Row, NULL)
                IF Status.Length < 185 THEN
                  Status.Length = Status.Length + 5
                  Status.Length = Status.Length + Fruit.Level
                END IF
                CALL BarStatus(Status)
                Pill.Active = FALSE
           
            CASE APPLE, PEAR
                IF ImageOn(Col, Row) = PEAR THEN
                   Fruit.Pears = Fruit.Pears + 1
                ELSE
                   Fruit.Apples = Fruit.Apples + 1
                END IF
                Fruit.Total = Fruit.Total + 1
                Fruit.Level = Fruit.Level + 1
                Status.Score = Status.Score + Status.Length \ 2
                IF Fruit.Total / 20 - Fruit.Total \ 20 = 0 THEN Status.Lives = Status.Lives + 1
                IF Fruit.Level = 10 THEN Done = TRUE
                CALL Image(Col, Row, NULL)
                IF Status.Length < 200 THEN Status.Length = Status.Length + Fruit.Level
                CALL BarStatus(Status)

                '  open the portal if ready
                IF Status.Score >= Required AND NOT Port.Active THEN CALL NewImage(PORTAL)

            CASE BLOCKHOLE, BRICKHOLE
                PtIn = 1: PtOut = 2
                IF Col = PortHole(2).Col AND Row = PortHole(2).Row THEN SWAP PtIn, PtOut
                Col = PortHole(PtOut).Col
                Row = PortHole(PtOut).Row
                IF Col = 11 THEN
                    Move = RIGHT
                ELSEIF Col = 80 THEN Move = LEFT
                ELSEIF Row = 3 THEN Move = DOWN
                ELSEIF Row = 50 THEN Move = UP
                END IF
                IF HoleIn = FALSE THEN
                    HoleIn = TRUE
                    Status.Score = Status.Score + Status.Length
                    CALL BarStatus(Status)
                END IF
                CALL DetectBlock(Col, Row, Move)
           
            CASE HOLEOPEN, PORTAL, PORTAL + &H10
                Front = Assign - 1
                IF Front = 0 THEN Front = 1
                DO UNTIL Assign = Front
                    CALL Image(Body(Assign).Col, Body(Assign).Row, Ground(Assign))
                    Assign = Assign + 1
                    IF Assign > Status.Length THEN Assign = 1
                   
                    IF Pill.Active THEN CALL SpinThePill
                    IF Port.Active THEN CALL FlashThePort
                   
                    Delay OptionsData.Slither
                    kb$ = RIGHT$(INKEY$, 1)
                    IF kb$ = CHR$(UP) THEN
                        EXIT DO
                    ELSEIF kb$ = CHR$(ESC) THEN
                        GameOver = TRUE
                        EXIT DO
                    END IF
                LOOP
                Status.Level = Status.Level + &H1
                EXIT DO
       
        END SELECT
       
        IF Done THEN
            IF ImageOn(Home.Col, Home.Row) <> SNAKE THEN
               IF OptionsData.Home = optHOMELESS THEN CALL NewImage(SNAKE)
               Grid(Home.Col, Home.Row) = HOLEOPEN
               CALL Image(Home.Col, Home.Row, HOLEOPEN)
               Done = FALSE
            END IF
        END IF
       
        '   store new Assign
        Body(Assign).Col = Col
        Body(Assign).Row = Row
        Body(Assign).Active = Move
        Ground(Assign) = ImageOn(Col, Row)

        '   draw Assign
        CALL Image(Body(Assign).Col, Body(Assign).Row, SNAKE)
       
        '   another continue?
        IF Status.Score >= Next.Continue THEN
            Status.Continue = Status.Continue + 1
            Next.Continue = Next.Continue * 2
        END IF

        '   delay
        CALL Delay(OptionsData.Slither)

        '   get input
        kb$ = INKEY$
        SELECT CASE RIGHT$(kb$, 1)
            CASE CHR$(UP): IF Move <> DOWN THEN Move = UP
            CASE CHR$(DOWN): IF Move <> UP THEN Move = DOWN
            CASE CHR$(LEFT): IF Move <> RIGHT THEN Move = LEFT
            CASE CHR$(RIGHT): IF Move <> LEFT THEN Move = RIGHT
            CASE CHR$(SPACE), "P", "p", CHR$(ENTER)
               
                CALL Box(41, 12, 46, 12)
                CALL gPrint(41, 12, "Pause", FALSE)
                i$ = INPUT$(1): Replace
            CASE CHR$(ESC)
                EXIT SUB
        END SELECT
    LOOP UNTIL Died
    IF Died THEN
        Status.Lives = Status.Lives - 1
        IF Status.Lives = 0 THEN GameOver = TRUE
        CALL BarStatus(Status)
    END IF
    IF GameOver AND Status.Continue > 0 THEN
        PCOPY 0, 1
        CALL Box(39, 11, 53, 12)
        CALL gPrint(39, 11, "Continues " + STR$(Status.Continue), FALSE)
        CALL gPrint(39, 12, "Try again  Y/N", FALSE)
        go = FALSE
        DO
            DO
                keyhit$ = INKEY$
            LOOP WHILE keyhit$ = ""
            SELECT CASE keyhit$
                CASE CHR$(ESC), "N", "n"
                    go = TRUE
                CASE CHR$(ENTER), "Y", "y", CHR$(SPACE)
                    GameOver = FALSE
                    Status.Continue = Status.Continue - 1
                    Status.Lives = 4
                    go = TRUE
            END SELECT
        LOOP UNTIL go
        PCOPY 1, 0
    END IF
LOOP UNTIL GameOver
CALL Box(40, 12, 49, 12)
CALL gPrint(40, 12, "Game Over", FALSE)
i$ = INPUT$(1): Replace

END SUB

'   set options/start/exit
SUB MainMenu (quit%)

DIM Opts(1 TO 19, 1 TO 2) AS STRING
DIM BlueBox(1 TO 32) AS INTEGER

LINE (10, 10)-STEP(7, 7), 3, BF
GET (10, 10)-STEP(7, 7), BlueBox(1)
LINE (10, 10)-STEP(7, 7), 0, BF

RESTORE OptsData
FOR x = 1 TO 19
    READ Opts(x, 1)
    READ Opts(x, 2)
NEXT x

Lel = 1
min = 1: max = 5
Device = optKEYS
go = FALSE

GOSUB PrintMenu
GOSUB high

DO
    DO
        kb$ = INKEY$
    LOOP WHILE kb$ = ""
    GOSUB low
    SELECT CASE kb$
        CASE CHR$(ENTER), CHR$(SPACE)
            SELECT CASE opt
                CASE 1: go = TRUE                     ' Start the game
                CASE 2: min = 6: max = 10
                    GOSUB PrintMenu                   ' View options
                CASE 3
                    CALL HowToPlay                    ' How to play
                    GOSUB PrintMenu
                CASE 4                                ' Preview
                    CALL Preview: GOSUB PrintMenu
                CASE 5                                ' Exit
                    quit% = TRUE
                    go% = TRUE
                CASE 6: min = 11: max = 13: Lel = 2
                    GOSUB PrintMenu
                CASE 7: min = 14: max = 15: Lel = 2
                    GOSUB PrintMenu
                CASE 8: min = 16: max = 17: Lel = 2
                    GOSUB PrintMenu
                CASE 9: min = 18: max = 19: Lel = 2
                    GOSUB PrintMenu
                CASE 10: min = 1: max = 5: Lel = 1
                    GOSUB PrintMenu
                CASE 11
                    OptionsData.Slither = FAST: GOSUB OptsMenu
                CASE 12
                    OptionsData.Slither = SLOW: GOSUB OptsMenu
                CASE 13
                    CALL CustomSpeed: GOSUB OptsMenu
                CASE 14
                    OptionsData.Home = optSHELTERED: GOSUB OptsMenu
                CASE 15
                    OptionsData.Home = optHOMELESS: GOSUB OptsMenu
                CASE 16
                    OptionsData.PowerHead = optBALLCAP: GOSUB OptsMenu
                CASE 17
                    OptionsData.PowerHead = optHARDHAT: GOSUB OptsMenu
                CASE 18
                    OptionsData.Growth = optAPPLESAUCE: GOSUB OptsMenu
                CASE 19
                    OptionsData.Growth = optSTEROIDS: GOSUB OptsMenu
            END SELECT
        CASE CHR$(ESC): END
        CASE CHR$(0) + CHR$(UP)
            opt = opt - 1
            IF opt < min THEN opt = max
        CASE CHR$(0) + CHR$(DOWN)
            opt = opt + 1
            IF opt > max THEN opt = min
    END SELECT
    GOSUB high

LOOP UNTIL go

EXIT SUB

high:
    FOR x = 1 TO LEN(Opts(opt, 1))
        PUT ((x * 8 - 8) + (Col * 8 - 8), (15 + opt - min) * 8 - 10), BlueBox(1), XOR
    NEXT x
    CALL gPrint(optCENTER, 22, SPACE$(15) + Opts(opt, 2) + SPACE$(15), -1)
RETURN
low:
    FOR x = 1 TO LEN(Opts(opt, 1))
        PUT ((x * 8 - 8) + (Col * 8 - 8), (15 + opt - min) * 8 - 10), BlueBox(1), XOR
    NEXT x
RETURN
PrintMenu:
    IF Lel = 1 THEN Col = 150 ELSE Col = 356
    LINE (Col, 100)-(500, 190), 0, BF
   
    IF Lel = 1 THEN Col = 33 ELSE Col = 46
    FOR y = 0 TO max - min
        CALL gPrint(Col, 15 + y, Opts(y + min, 1), FALSE)
    NEXT y
    opt = min
RETURN
OptsMenu:
    min = 6: max = 10: Lel = 1
    GOSUB PrintMenu
RETURN
END SUB

'  places a new instance of the specified image randomly on the screen
SUB NewImage (Img%)

SELECT CASE Img
   CASE PEAR, APPLE

      '   print 9 apples and 1 pear
      FOR x = 1 TO 10

          '   generate random points
          DO
              A = INT(RND * 67) + 12
              B = INT(RND * 44) + 4
          LOOP WHILE ImageOn(A, B) <> NULL
           
          '   assign apple or pear
          IF x = 10 THEN
              CALL Image(A, B, PEAR)
          ELSE
              CALL Image(A, B, APPLE)
          END IF

      NEXT x

   CASE BRICKHOLE, BLOCKHOLE

      FOR p = 1 TO 2
          DO
              good = FALSE
              y = INT(RND * 69) + 11
              x = INT(RND * 47) + 3
              IF Solid(y, x) AND (NOT Solid(y - 1, x) OR NOT Solid(y + 1, x) OR NOT Solid(y, x - 1) OR NOT Solid(y, x + 1)) THEN good = TRUE
          LOOP UNTIL good
         
          PortHole(p).Col = y
          PortHole(p).Row = x
          IF Solid(y, x) = BLOCK THEN ima = BLOCKHOLE ELSE ima = BRICKHOLE
          CALL Image(y, x, ima)
      NEXT p

   CASE SNAKE

      DO
          y = INT(RND * 67) + 12
          x = INT(RND * 44) + 4
          ima = ImageOn(y, x)
      LOOP WHILE ima = BLOCK OR ima = BRICK OR ima = SNAKE
      Home.Col = y
      Home.Row = x

   CASE STEROID

      DO
          Col = INT(RND * 67) + 12
          Row = INT(RND * 44) + 4
          ima = ImageOn(Col, Row)
      LOOP UNTIL ima = NULL
      Pill.Col = Col
      Pill.Row = Row
      CALL Image(Pill.Col, Pill.Row, STEROID)

   CASE PORTAL

      DO
          Col = INT(RND * 67) + 12
          Row = INT(RND * 44) + 4
          ima = ImageOn(Col, Row)
      LOOP WHILE ima > PEAR
      Port.Col = Col
      Port.Row = Row
      CALL Image(Port.Col, Port.Row, PORTAL)

END SELECT

END SUB

SUB Preview

DIM Status AS StatusType
Status.Level = 1

DO
   CALL Level(Status)
   DO
      kb$ = INKEY$
   LOOP WHILE kb$ = ""
   SELECT CASE RIGHT$(kb$, 1)
      CASE CHR$(UP), CHR$(LEFT)
         Status.Level = Status.Level + 1
         IF Status.Level > 15 THEN Status.Level = 1
      CASE CHR$(DOWN), CHR$(RIGHT)
         Status.Level = Status.Level - 1
         IF Status.Level = 0 THEN Status.Level = 15
   END SELECT

LOOP UNTIL kb$ = CHR$(ESC)
CALL Intro

END SUB

'  replaces a saved portion of the screen
SUB Replace

SHARED TextTemp() AS INTEGER
SHARED Caught AS GenType

IF Caught.Col > 0 THEN
   PUT (Caught.Col, Caught.Row), TextTemp, PSET
   ERASE TextTemp
END IF

Caught.Col = 0
Caught.Row = 0

END SUB

'   resets the snake path
SUB ResetSnake (Body() AS GenType, Ground() AS INTEGER)

FOR x = 1 TO 200
    Body(x).Col = 1
    Body(x).Row = 50
    Ground(x) = NULL
NEXT x

END SUB

'  detects a brick or block at a specified point
FUNCTION Solid% (y, x)

Solid% = FALSE
ima = ImageOn(y, x)
IF ima = BRICK OR ima = BLOCK THEN Solid% = ima

END FUNCTION

'  spins the steroid pill
SUB SpinThePill
STATIC Rotation%

IF Pill.Active THEN

   Rotation% = Rotation% + 1
   IF Rotation% = 4 THEN Rotation% = 0

   CALL Image(Pill.Col, Pill.Row, STEROID + (Rotation * Img))
END IF

END SUB
1
Hosted by www.Geocities.ws