Snazzy Snake

Back in 1982 (or possibly 1983) while I was at University I wrote the following program which is the oldest program to which I have any form of recording. It was written for the BBC Micro and was also provided to Simon (one of my lecturers who went by the singular name) and included in the book Quality Programs for the BBC Micro1. Given the nature of the book the program is now released under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.

If you get the chance it's worth reading both the specific chapter on this program and indeed the complete book. Simon's very mild criticism of my programming style is fun to read all these years after the event (and I can tell my programming lineage via the Commodore Pet still shows through!). I also note that some of the formatting and styling of the program not what I would do today - whether that formatting is more to do with the layout required for the book or more to do with my style of coding back in the day is something I can't answer!2

 100 REM Snazzy Snake, by David Vines
 110 ON ERROR GOTO 240
 120 MODE7
 130 VDU23;8202;0;0;0;: *FX4,1
 140 PROCINIT
 150 REPEAT
 160   PROCSETUP: PROCSCREEN
 170   REPEAT: PROCSNAKE: PROCNUMBER
 180   UNTIL TIME>6000
 190   PROCENDGAME
 200 UNTIL FNEND
 210 PROCCLEANUP: MODE 7
 220 END
 229
 230 REM ERROR HANDLING
 240 PROCCLEANUP
 250 REPORT: IF ERL>0 THEN PRINT" at line ";ERL
 260 END
 269
 270 DEF PROCINIT
 280 HIGHSCORE=0: *FX11,0
 290 max=500: DIM xpos(max),ypos(max),D$(4)
 300 D$(1)="^": D$(2)="]": D$(3)="V"; D$(4)="["
 310 PROCINSTRUCTIONS
 320 ENDPROC
 329
 330 DEF PROCINSTRUCTIONS
 340 CLS
 350 FOR I=1 TO 2
 360   VDU132,157,135,141: PRINTSPC(5)"SNAZZY SNAKE";
 370   VDU140: IF I=1 THEN PRINT" By David Vines"
 380 NEXT
 390 PRINT''"  This is a game for one player. The"
 400 PRINT"game represents a snake, trapped in an"
 410 PRINT"enclosed area, who has tto keep eating"
 420 PRINT"in order to survive. The snake eats"
 430 PRINT"his food by hitting it."
 440 PRINT'"  The snake is controlled by the cursor"
 450 PRINT"keys. The ""["" key turns the snake to"
 460 PRINT"its left, the ""]"" key turns it to"
 470 PRINT"its right. The snake initially has one"
 480 PRINT"minute to survive, but each piece of"
 490 PRINT"food he eats means that he can live"
 500 PRINT"longer. The score is the total value of"
 510 PRINT"food eaten by the snake."
 520 PRINT'''"   ";: VDU132,157,135
 530 PRINT"PRESS ANY KEY TO START  ";:VDU 156,30
 540 A$=GET$
 550 ENDPROC
 559
 560 DEF PROCSETUP
 570 SCORE=0: TIME=0: NX=4: NY=4: value=0: Head=2
 580 Length=2: Real_Length=2: Tail=0; DIR=1
 590 xpos(Head)=19: ypos(Head)=10: xpos(Head-1)=19
 600 ypos(Head-1)=11: xpos(Tail)=19: ypos(Tail)=12
 610 ENDPROC
 619
 620 DEF PROCSCREEN
 630 CLS: PROCTOPLINE: PRINT
 640 FOR I=1 TO 39: VDU 255: NEXT
 650 FORJ=2 TO 21: VDU31,0,J,255,31,38,J,255: NEXT
 660 PRINTTAB(0,22);: FORI=1 TO 39: VDU 255: NEXT
 670 PRINTTAB(19,10)"^";TAB(19,11)"*";TAB(19,12)"*"
 680 ENDPROC
 689
 690 DEF PROCSNAKE
 700 PROCTOPLINE: I$=INKEY$(0)
 710 IF I$<>"" THEN PROCNEWDIR(I$)
 720 IF Length=Real_Length THEN PROCPOKE(xpos(Tail),ypos(Tail)," "): Tail=Tail+1: IF Tail>max THEN Tail=0
 730 IF Length>Real_Length THEN Real_Length=Real_Length+1
 740 OHead=Head: Head=Head+1: IF Head>max THEN Head=0
 750 IF DIR=1 THEN PROCadd(0,1) ELSE IF DIR=2 THEN PROCadd(1,0) ELSE IF DIR=3 THEN PROCadd(0,-1) ELSE PROCadd(-1,0)
 760 A$=FNPeek(xpos(Head),ypos(Head))
 770 IF A$=CHR$(255) OR A$="*" THEN TIME=7000
 780 PROCPOKE(xpos(OHead),ypos(OHead),"*")
 790 PROCPOKE(xpos(Head),ypos(Head),D$(DIR))
 800 IF ASC(A$)<>1 AND A$<>"#" THEN ENDPROC
 810 FOR I=value-1 TO 0 STEP -1
 820   PROCPOKE(NX,NY,STR$(I)): Length=Length+1
 830   PROCWAIT(0.05): SCORE=SCORE+1
 840   TIME=TIME-57: PROCTOPLINE
 850 NEXT
 860 value=0
 870 ENDPROC
 879
 880 DEF PROCNEWDIR(I$)
 890 IF I$=CHR$(&89) THEN DIR=DIR+1: IF DIR=5 THEN DIR=1
 900 IF I$=CHR$(&88) THEN DIR=DIR-1: IF DIR=0 THEN DIR=4
 910 ENDPROC
 919
 920 DEF PROCadd(x,y)
 930 xpos(Head)=xpos(OHead)+x: ypos(Head)=ypos(OHead)+y
 940 ENDPROC
 949
 950 DEF PROCNUMBER
 960 IF value<>0 AND RND(120)<>1 THEN ENDPROC
 970 FOR I=-1 TO 1: FOR J=-1 TO 1
 980    IF NX+I<>xpos(Head) OR NY+J<>ypos(Head) THEN PROCPOKE(NX+I,NY+J," ")
 990 NEXT:NEXT
1000 REPEAT
1010   NX=RND(35)+1: NY+RND(16)+2: valid=TRUE
1020   FOR I=-1 TO 1: FOR J=-1 TO 1
1030       valid=valid AND (FNPEEK(NX+I,NY+J)=" ")
1040   NEXT: NEXT
1050 UNTIL valid OR TIME>6000
1060 IF TIME>6000 THEN ENDPROC
1070 value=RND(9)
1080 FOR I=-1 TO 1: FOR J=-1 TO 1
1090     PROCPOKE(NX+I,NY+J,"#")
1100 NEXT: NEXT
1110 PROCPOKE(NX,NY,STR$(value))
1120 ENDPROC
1129
1130 DEF PROCENDGAME
1140 VDU28,4,17,36,8: CLS
1150 FOR J=3 TO 4:PRINTTAB(10,J)CHR$(141)"GAME OVER"CHR$(140): NEXT
1160 IF A$=CHR$(255) THEN PRINTTAB(0,1)" YOU'VE HIT A SIDE - OH DEAR ! "
1170 IF A$="*" THEN PRINTTAB(0,1)" YOU'VE HIT YOURSELF - A BAD MOVE "
1180 IF TIME<7000 THEN PRINTTAB(12,1)" TIME UP "
1190 PROCWAIT(1): IF SCORE>HIGHSCORE THEN HIGHSCORE+SCORE
1200 ENDPROC
1209
1210 DEF FNEND: LOCAL B$
1220 PRINTTAB(0,6)" ANOTHER GAME? (PRESS 'Y' OR 'N') "
1230 PRINTTAB(0,8)" (PRESS 'I' FOR INSTRUCTIONS) ": VDU26
1240 REPEAT
1250   B$=GET$
1260   IF B$="I" OR B$="i" THEN PROCINSTRUCTIONS: B$="Y"
1270 UNTIL INSTR("YyNn",B$)
1280 =B$="N" OR B$="n"
1289
1290 DEF PROCTOPLINE
1300 PRINTTAB(0,0);"SCORE+ ";SCORE;" TIME= ";
1310 @%=&20205: PRINT;60-TIME/100;: @%=10
1320 PRINT" HIGH SCORE= ";HIGHSCORE;" ";
1330 ENDPROC
1339
1340 DEF FNPEEK(X,Y)
1350 VDU31,X,Y
1360 A%=135
1370 =CHR$((USR(&FFF4) AND &FFFF) DIV &100)
1379
1380 DEF PROCPOKE(X,Y,X$)
1390 VDU 31,X,Y,ASC(X$)
1400 ENDPROC
1409
1410 DEF PROCWAIT(T): LOCAL oldtime
1420 oldtime=TIME
1430 REPEAT UNTIL TIME-oldtime>T*100
1440 ENDPROC
1449
1450 DEF PROCCLEANUP
1460 *FX12,0
1470 *FX4,0
1480 @%=10
1490 ENDPROC

Footnotes

  1. ISBN 0-7447-0001-9 and had the princely price of £6.50
  2. And yes, some more comments would have been handy - but the program had to fit on a BBC Model A (which had only 16K bytes of RAM, of which 3¾K was used by the operating system and another 1K for the screen (this program uses the BBC Micro's teletext screen mode) leaving under 12K for the program itself AND all the variables it uses (including two 500 element arrays each of holds a floating point number and hence uses about 2K just on those array. In any event there just wasn't much room for comments!