!**************************************************************************
!SNAKE.BAS    10/26/88
!
!by Steve Archuleta - AMUS Staff
!
!NEEDS INKEY.SBR (INKEY.M68 in [100,52])
!
!Directions:
!     The purpose of this two-player game is to move your snake across the
! road, without being run over by a car, as many times as possible. The "D"
! and "K" keys are used to move snakes 1 and 2, respectively, one lane at a
! time. Each time the road is crossed, one point is scored. If a snake is
! run over, it will be unable to move for a short time. There is also a
! short delay after a point has been scored to discourage players from
! continuously holding down the keys. This game is best played on a 19200
! baud terminal. The difficulty level can be changed by making the change
! described in the SQUASHED routine.
!**************************************************************************

MAP1    WAIT,F                          !dummy var
MAP1    ANSWER,S,1                      !continue game var
MAP1    GAME'TIME,F,6                   !length of game counter
MAP1    SNAKE,S,1,"|"                   !snake character
MAP1    ROAD'KILL,S,1,"*"               !smashed snake character
MAP1    LANE,F,6                        !road lane (row coordinate)
MAP1    STRIPE,F,6                      !road stripe (col coordinate)
MAP1    RESP,S,1                        !input buffer char
MAP1    SCRMAP(21,80),F,6               !array to keep track of cars position
MAP1    SCORE1,F,6                      !player 1 score
MAP1    SCORE2,F,6                      !player 2 score
MAP1    DELAY1,F,6                      !player 1 delay counter
MAP1    DELAY2,F,6                      !player 2 delay counter
MAP1    SX1,F,6                         !snake 1 coordinates
MAP1    SY1,F,6,21
MAP1    SX2,F,6                         !snake 2 coordinates
MAP1    SY2,F,6,61
MAP1    CAR1,S,8,"  [=]>"               !cars 1 - 8
MAP1    CAR2,S,16," [IIIII]>"
MAP1    CAR3,S,10,"   [==]:"
MAP1    CAR4,S,6,"    =>"
MAP1    CAR5,S,8,"{##]    "
MAP1    CAR6,S,16,":(|||||) "
MAP1    CAR7,S,10,"<*||]   "
MAP1    CAR8,S,10,"(]\\)    "
MAP1    X1,F,6                          !car coordinates 1 - 8
MAP1    Y1,F,6
MAP1    X2,F,6
MAP1    Y2,F,6
MAP1    X3,F,6
MAP1    Y3,F,6
MAP1    X4,F,6
MAP1    Y4,F,6
MAP1    X5,F,6
MAP1    Y5,F,6
MAP1    X6,F,6
MAP1    Y6,F,6
MAP1    X7,F,6
MAP1    Y7,F,6
MAP1    X8,F,6
MAP1    Y8,F,6

       ? TAB(-1,29)
       ? TAB(-1,0)
       ? TAB(3,14)     "SSSSSSSS  NN     NN  AAAAAAAAA  KK   KK  EEEEEEEE"
       ? TAB(4,14)     "SS        NNN    NN  AA     AA  KK  KK   EE"
       ? TAB(5,14)     "SS        NN N   NN  AA     AA  KK KK    EE"
       ? TAB(6,14)     "SSSSSSSS  NN  N  NN  AAAAAAAAA  KKK      EEEEEE"
       ? TAB(7,14)     "      SS  NN   N NN  AA     AA  KK KK    EE"
       ? TAB(8,14)     "      SS  NN    NNN  AA     AA  KK  KK   EE"
       ? TAB(9,14)     "SSSSSSSS  NN     NN  AA     AA  KK   KK  EEEEEEEE"
       ? TAB(24,27);
       INPUT "Press Return to Continue -> ",WAIT

START:
       CALL INITIALIZE
       CALL DRAW'ROAD
LOOP:   CALL MOVE'CARS
       CALL GETKEY
       CALL SQUASHED
       CALL UPDATE
       DELAY1 = DELAY1 - 1 : DELAY2 = DELAY2 - 1
       CALL GETKEY
       CALL SQUASHED
       CALL UPDATE
       GOTO LOOP

!*********************************************************
! INITIALIZE - Turn off cursor, clear screen, and set    *
! initial game variables.                                *
!*********************************************************
INITIALIZE:
       ? TAB(-1,29)
       ? TAB(-1,0)
       ON ERROR GOTO END
       GAME'TIME = 0
       SCORE1 = 0 : SCORE2 = 0
       DELAY1 = 0 : DELAY2 = 0
       SX1 = 21 : SX2 = 21             !snake starting positions
       X1 = 3 : Y1 = -1                !cars 1 - 8 starting positions
       X2 = 5 : Y2 = 0
       X3 = 7 : Y3 = -2
       X4 = 9 : Y4 = -3
       X5 = 13 : Y5 = 77
       X6 = 15 : Y6 = 73
       X7 = 17 : Y7 = 76
       X8 = 19 : Y8 = 76
       RETURN

!*********************************************************
! DRAW'ROAD - Draw initial game screen.                  *
!*********************************************************
DRAW'ROAD:
       FOR LANE = 2 TO 20 STEP 2
        IF ((LANE <> 10) AND (LANE <> 12)) THEN &
         FOR STRIPE = 2 TO 78 STEP 2 :&
           ? TAB(LANE,STRIPE) "-"; :&
         NEXT STRIPE
       NEXT LANE
       LANE = 11
       FOR STRIPE = 2 TO 78 STEP 2
         ? TAB(LANE,STRIPE) "=";
       NEXT STRIPE
       ? TAB(24,1) "Snake 1:";
       ? TAB(24,61) "Snake 2:";
       ? TAB(SX1,SY1) SNAKE;
       ? TAB(SX2,SY2) SNAKE;
       RETURN

!*********************************************************
! MOVE'CARS - Move each car one position forward and     *
! update car's position via SCRMAP routine.  Note that   *
! cars have various "speeds" and that the blanks         *
! included within the cars definitions are crucial to    *
! the appearance of motion.                              *
!*********************************************************
MOVE'CARS:
       Y1 = Y1 + 2
       ? TAB(X1,Y1) CAR1;
       CALL SCRMAP1
       Y2 = Y2 + 1
       ? TAB(X2,Y2) CAR2;
       CALL SCRMAP2
       Y3 = Y3 + 3
       ? TAB(X3,Y3) CAR3;
       CALL SCRMAP3
       Y4 = Y4 + 4
       ? TAB(X4,Y4) CAR4;
       CALL SCRMAP4
       Y5 = Y5 - 4
       ? TAB(X5,Y5) CAR5;
       CALL SCRMAP5
       Y6 = Y6 - 1
       ? TAB(X6,Y6) CAR6;
       CALL SCRMAP6
       Y7 = Y7 - 3
       ? TAB(X7,Y7) CAR7;
       CALL SCRMAP7
       Y8 = Y8 - 4
       ? TAB(X8,Y8) CAR8;
       CALL SCRMAP8
       RETURN

!*********************************************************
! GETKEY - Use INKEY.SBR to retrieve next key from input *
! buffer. If "D" move snake 1; if "K" move snake 2. If   *
! snake has reached top of screen, increment score, move *
! snake to bottom and provide a short delay.             *
!*********************************************************
GETKEY: XCALL INKEY,RESP
       RESP = UCS(RESP)
       IF DELAY1 > 0 THEN GOTO SKIP1 else ? TAB(SX1,SY1) SNAKE;
       IF RESP = "D" THEN ? TAB(SX1,SY1) " "; : SX1 = SX1 -2 :&
       ? TAB(SX1,SY1) SNAKE;
       IF SX1 = 1 THEN ? TAB(SX1,SY1) " "; : SX1 = 21 : &
       ? TAB(SX1,SY1) SNAKE; : SCORE1 = SCORE1 + 1 :&
       ? TAB(24,10) SCORE1; : DELAY1 = 5

SKIP1:  IF DELAY2 > 0 THEN GOTO SKIP2 else ? TAB(SX2,SY2) SNAKE;
       IF RESP = "K" THEN ? TAB(SX2,SY2) " "; : SX2 = SX2 - 2 :&
       ? TAB(SX2,SY2) SNAKE;
       IF SX2 = 1 THEN ? TAB(SX2,SY2) " "; : SX2 = 21 : &
       ? TAB(SX2,SY2) SNAKE; : SCORE2 = SCORE2 + 1 :&
       ? TAB(24,70) SCORE2; : DELAY2 = 5
SKIP2:  RETURN

!*********************************************************
! SQUASHED - Check to see if snake has been run over.    *
! If so, print road kill char, ding bell and set delay   *
! penalty. Otherwise, continue as normal. To make the    *
! game harder, change SX1 = SX1 + 2 to SX1 = 21. Do the  *
! same for SX2.                                          *
!*********************************************************
SQUASHED:
       IF SCRMAP(SX1,SY1) = 1 THEN SX1 = SX1 + 2 :&
       ? TAB(SX1,SY1) ROAD'KILL; : ? CHR(7); : DELAY1 = 15
       IF SCRMAP(SX2,SY2) = 1 THEN SX2 = SX2 + 2 :&
       ? TAB(SX2,SY2) ROAD'KILL; : ? CHR(7); : DELAY2 = 15
       RETURN

!*********************************************************
! UPDATE - Check to see if cars are at end of screen.    *
! If so, erase car and set horizontal position back to   *
! start position. GAME'TIME controls the length of the   *
! game.                                                  *
!*********************************************************
UPDATE: IF Y1 = 75 THEN Y1 = -1 : ? TAB(X1,77) "    "; :&
       GAME'TIME = GAME'TIME + 1
       IF Y2 = 72 THEN Y2 =  0 : ? TAB(X2,73) "        ";
       IF Y3 = 73 THEN Y3 = -2 : ? TAB(X3,76) "     ";
       IF Y4 = 73 THEN Y4 = -3 : ? TAB(X4,77) "  ";
       IF Y5 = 1  THEN Y5 = 77 : ? TAB(X5,1)  "    ";
       IF Y6 = 1  THEN Y6 = 73 : ? TAB(X6,1)  "        ";
       IF Y7 = 1  THEN Y7 = 76 : ? TAB(X7,1)  "     ";
       IF Y8 = 4  THEN Y8 = 76 : ? TAB(X8,4)  "     ";
       IF GAME'TIME = 10  THEN GOTO EXIT
       RETURN

!*********************************************************
! SCRMAP - Keep track of car's position on screen by     *
! filling in array. 1's indicate the presence of the     *
! car at any particular position.                        *
!*********************************************************
SCRMAP1:
       SCRMAP(X1,Y1) = 0 : SCRMAP(X1,Y1+1) = 0 : SCRMAP(X1,Y1+2) = 1
       SCRMAP(X1,Y1+3) = 1 : SCRMAP(X1,Y1+4) = 1 : SCRMAP(X1,Y1+5) = 1
       RETURN

SCRMAP2:
       SCRMAP(X2,Y2) = 0 : SCRMAP(X2,Y2+1) = 1 : SCRMAP(X2,Y2+2) = 1
       SCRMAP(X2,Y2+3) = 1 : SCRMAP(X2,Y2+4) = 1 : SCRMAP(X2,Y2+5) = 1
       SCRMAP(X2,Y2+6) = 1 : SCRMAP(X2,Y2+7) = 1 : SCRMAP(X2,Y2+8) = 1
       RETURN

SCRMAP3:
       SCRMAP(X3,Y3) = 0 : SCRMAP(X3,Y3+1) = 0 : SCRMAP(X3,Y3+2) = 0
       SCRMAP(X3,Y3+3) = 1 : SCRMAP(X3,Y3+4) = 1 : SCRMAP(X3,Y3+5) = 1
       SCRMAP(X3,Y3+6) = 1 : SCRMAP(X3,Y3+7) = 1