Snake
TMCD677 (tvgames.me)
Locomotive BASIC v1.1
PUR-120
Introduction
------------
My first attempt at writing a complete game limited to 10 Lines. Chosen Locomotive BASIC (Amstrad CPC)
for auld lang syne. Pretty simple game many will remember from their old Nokia mobile phones in the
early 2000's. Code is under 800 characters but a couple of lines squeek over 80 characters hence PUR-120.
Game would easily be PUR-80 in just about anyother 8-bit dialect.
Loading
-------
The provided DSK image contains 8 versions of the game (most not working). Insert the disk into your
favourite Amstrad CPC Emulator and execute:
LOAD"Snake8
RUN
In either CPC664 or CPC6128 modes.
The recomended emulator is CaPriCe Forever by Fredouille and can be downloaded from the CPC Power website
(https://www.cpc-power.com/cpcarchives/index.php?page=articles&num=445).
Controls
--------
Please make sure your keyboard is in lowercase mode (default) prior to running the game.
UP - 'p'
DOWN - 'l'
LEFT - 'z'
RIGHT - 'x'
Instructions
------------
The game starts with a small single segment snake in the centre of the screen automatically moving to the
left. Your task is to guide this snake around the screen eating numbers that will appear randomly
around the screen. Each time you eat a number your snakes body will grow by that number of segments.
However you need to be careful. The snake cannot move beyond the edges of the screen or cross its own
path. Hit the edge of the screen or the growing body of the snake and it's GAME OVER! Beware - the top
of the screen is at Line2, below the score line. Also, each time you eat a number the snakes movement
will speed up by that amount.
When the game ends press any key to return to Locomotive BASIC and execute:
RUN
for another game.
Scoring
-------
Snake is a high score challenge game. Who lasts the longest and eats the most numbers gets the highest
score and wins. You score 10pts each time the snake moves and the value of any numbers the snake eats.
Disk Catalogue
--------------
Snake1.BAS - Original 5 line concept test moving snake body around screen
Snake2.BAS - 1st attempt long listing; snake doesn't move; numbers appear randomly
Snake3.BAS - 10Liner version of Snake2
Snake4.BAS - 10Liner. Displays snake head, first random number, then hits GAME OVER
Snake5.BAS - Full anotated listing. Random numbers and snake growth are broken
Snake6.BAS - Fully working game, final full anotated listing - see listin below
Snake7.BAS - Fully working game. Snake 6 condensed. REM statments removed and variable names shortened
Snake8.BAS - 10Liner. Fully working game. Final fully working entry - see listing below
Fully Anotated Listing
----------------------
10 REM VARIABLES
20 DIM path(500,2) : REM snake body path co-ordinates stack
30 LET tsp=1 : REM tail stack pointer
40 LET hsp=1 : REM head stack pointer
50 LET x=10 : REM head x-axis co-ordinate
60 LET y=10 : REM head y-axis co-ordinate
70 LET i$="" : REM user input
80 LET score=-10 : REM player score
90 LET grow=0 : REM amount to grow snake by
100 LET c$="" : REM screen content
110 LET w=750 : REM wait time, snake speed
120 LET n=0 : REM random number
130 LET d$="z" : REM current direction
140 LET nx=0 : REM random number x-axis co-ordinate
150 LET ny=0 : REM random number y-axis co-ordinate
160 LET temp$="" : REM screen contents
170 LET flag=1 : REM random number display flag
200 REM SET-UP
210 MODE 0 : REM 20 characters x 25 lines
220 INK 0,1 : REM background colour (blue)
230 INK 1,24 : REM snake colour (yellow)
240 INK 2,26 : REM score colour (white)
250 INK 3,6 : REM number colour (red)
260 INK 4,6,26 : REM game over colour (flashing red+white)
300 REM START GAME LOOP
310 LET path(hsp,1)=x : REM store head x-axis in stack
320 LET path(hsp,2)=y : REM store head y-axis in stack
330 LET hsp=hsp+1 : REM increase head stack pointer
340 IF hsp>500 THEN hsp=1 : REM if head stack point at end of stack move to start
500 REM DISPLAY
510 LOCATE x,y : REM goto new head position
520 PEN 1 : REM use yellow ink
530 PRINT "*"; : REM display snake head
540 LET score=score+10 : REM add 10 to score for each move
550 PEN 2 : REM use white ink
560 LOCATE 12,1 : REM goto score display position
570 PRINT score; : REM update score
580 FOR s=1 TO w:NEXT s : REM wait for snake speed
590 IF grow<>0 THEN LET grow=grow - 1 ELSE LOCATE path(tsp,1),path(tsp,2):PRINT " ";:LET tsp=tsp+1:IF tsp>500 THEN LET tsp=1
595 REM if snake not growing then remove body from current tail position
700 REM USER INPUT AND MOVEMENT
710 LET i$=INKEY$ : REM get user input
720 IF i$<>"" THEN LET d$=i$ : REM if input detected update direction
730 IF d$="z" THEN LET x=x-1 : REM if user presses "z" move left
740 IF d$="x" THEN LET x=x+1 : REM if user presses "x" move right
750 IF d$="p" THEN LET y=y-1 : REM if user presses "p" move up
760 IF d$="l" THEN LET y=y+1 : REM if user presses "l" move down
800 REM COLLITION DETECTION
810 IF x<1 OR x>20 OR y<2 OR y>25 THEN GOTO 1000
815 REM end game if hit edge of screen
820 LOCATE x,y : REM goto next head position
830 LET temp$=COPYCHR$(#0) : REM get any characters currently at that position
840 IF temp$="*" THEN GOTO 1000: REM end game if snake head touches body
850 IF temp$<>" " THEN LET grow=n:LET score=score+n:LET w=w-n:LET flag=1
855 REM if head finds number add to score and grow snake
900 REM RANDOM NUMBERS
910 IF flag=0 THEN GOTO 300 : REM if not collected next number
920 LET n=INT((RND(1)*9)+1) : REM choose a random numner (1..9)
930 LET nx=INT((RND(1)*20)+1) : REM choose random x co-ordinate for random number
940 LET ny=INT((RND(1)*25)+1) : REM choose random y co-ordinate for random number
950 IF ny=1 THEN GOTO 930 : REM if y-cordinate on score line choose another
960 LOCATE nx,ny : REM goto chosen random number position
970 LET temp$=COPYCHR$(#0) : REM get any characters already there
980 IF temp$="*" THEN GOTO 930 : REM choose new location if snake body is there
990 PEN 3:PRINT n;: LET flag=0 : REM display new random number if needed
999 GOTO 300 : REM back to start of game loop
1000 REM GAME OVER
1010 PEN 4 : REM use flashing ink
1020 LOCATE 2,10 : REM centre message on screen
1030 PRINT "G A M E O V E R";: REM display game over message
1040 LET i$=inkey$ : REM get user input
1050 IF i$="" THEN GOTO 1040 : REM keep waiting until user presses a key
1060 PEN 1 : REM use default OS ink colour
Final 10 Liner Listing
----------------------
1 DIM p(500,2):t=1:h=1:x=10:y=10:s=-10:m=750:d$="z":f=1:MODE 0:INK 2,26:INK 3,6:INK 4,6,26
2 p(h,1)=x:p(h,2)=y:h=h+1:LOCATE x,y:PEN 1:?"*";:s=s+10:PEN 2:LOCATE 12,1:? s;:FOR z=1 TO m:NEXT:IF h>500 THEN h=1
3 IF g<>0 THEN g=g-1 ELSE LOCATE p(t,1),p(t,2):?" ";: t=t+1:IF t>500 THEN t=1
4 i$=INKEY$:IF i$<>"" THEN d$=i$
5 IF d$="z" THEN x=x-1 ELSE IF d$="x" THEN x=x+1 ELSE IF d$="p" THEN y=y-1 ELSE IF d$="l" THEN y=y+1
6 IF x<1 OR x>20 OR y<2 OR y>25 THEN GOTO 10
7 LOCATE x,y:c$=COPYCHR$(#0):IF c$="*" THEN GOTO 10 ELSE IF c$<>" " THEN g=g+n:s=s+n:m=m-n:f=1
8 IF f=0 THEN GOTO 2 ELSE n=INT((RND(1)*9)+1):v=INT((RND(1)*20)+1):w=INT((RND(1)*25)+1):IF w=1 THEN GOTO 8
9 LOCATE v,w:c$=COPYCHR$(#0):IF c$="*" THEN GOTO 8 ELSE PEN 3:? n;:f=0:GOTO 2
10 PEN 4:LOCATE 2,10:?"G A M E O V E R";:i$=inkey$:IF i$="" THEN GOTO 10 ELSE PEN 1