Worm

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Arcade

Worm is a snake game. You steer an ever-growing, always hungry centipede around the screen to eat leaves (^), lemons (*) and flowers (@), which appear at random. Running into a red block or into your own body costs a life, and more red blocks appear as the game goes on. You have five lives, the points per item go up with the life you are on, and a beep confirms each turn. At the end, a top-ten table records high scores with three initials. You can play on the keyboard (5, 7 and 8) or with a joystick.

The program has no credit. It was found on two of Butch Weinberg’s Larken disks.

Program Analysis

Movement

The worm’s body is stored as row and column bytes in a$(2,630). Each move adds a new head position (line 115), and line 35 removes the tail by shifting the whole array left with a slice assignment. Collisions are found by reading the screen with SCREEN$ (l,c): "#" or "O" means death, and ^, * and @ score points. The joystick is read with the TS2068 STICK function (shown as | in some listings). STICK(2,1) reads the fire button on the “press a key” screen.

Hazards and scoring

Line 120 places a new item 30% of the time, and line 155 adds a growing number of red blocks every 13 moves. A leaf or flower scores 1*(1+liv) and a lemon 3*(1+liv). The game-over routine plays a tune from DATA line 9999 and inserts the score into the table held in a() and p$().

Notable Techniques

  • Tail removal by string-slice shifting rather than a ring buffer.
  • Screen-based collision detection with SCREEN$.
  • TS2068 ON ERR and STICK keywords.
  • POKE 23658,8 turns on CAPS LOCK while the initials are typed.

Potential Issues

  • The instructions mention the arrow keys, but only 5 (left), 7 (up) and 8 (right) are checked. There is no key for down. The worm starts out moving down, and on the keyboard it can never turn down again.
  • The column and row limits allow the worm to leave the screen. Line 15 sets ON ERR CONTINUE to cover this, but in ZEsarUX on a stock TS2068 ROM the error was not trapped: running into an edge stopped the program with “5 Out of screen”.
  • The instructions say flowers are worth 5 points, but the code scores them the same as leaves.
  • Lines 9982–9983 are a leftover endless SAVE loop.

This copy came from a Larken disk. For tape, the LKDOS prefixes were removed from the SAVE and LOGICALL lines, and the saved variables (an empty score table) were dropped. Line 5 creates the table again. It was tested in ZEsarUX on a stock TS2068.

Image Gallery

Source Code

    5 RANDOMIZE : DIM a(11): DIM p$(11,3): GO TO 220
   10 CLS 
   15 ON ERR RESET : ON ERR CONTINUE 
   20 INK 5: FOR i=k TO k+long: PRINT AT CODE a$(1,i),CODE a$(2,i);"O": GO SUB 40: GO SUB 120: NEXT i: INPUT "": PRINT #1; INK 5;"Lives=";liv;TAB 13;"Score=";sc;" "
   25 GO SUB 35: GO SUB 120: LET cnt=cnt+1: IF cnt=13 THEN LET g=g+RND: GO SUB 170: LET cnt=0
   30 GO SUB 35: LET g=g+RND: GO TO 20
   35 FOR q=1 TO 2: PRINT AT CODE a$(1,1),CODE a$(2,1);" ": LET a$(1,1 TO 629)=a$(1,2 TO 630): LET a$(2,1 TO )=a$(2,2 TO ): LET k=k-1: NEXT q: RETURN 
   40 LET a=|(1,1): IF j=0 AND (a=5 OR a=6 OR a=9 OR a=10) THEN GO TO 70
   45 IF j=0 AND |(1,1)<>0 THEN LET dir=|(1,1): GO TO 70
   50 IF INKEY$="5" THEN LET dir=4
   60 IF INKEY$="7" THEN LET dir=1
   65 IF INKEY$="8" THEN LET dir=8
   70 IF dir=1 THEN LET l=l-(1 AND l>1): GO TO 90
   75 IF dir=8 THEN LET c=c+(1 AND c<32): GO TO 90
   80 IF dir=2 THEN LET l=l+(1 AND l<22): GO TO 90
   85 IF dir=4 THEN LET c=c-(1 AND c>-1)
   90 IF odir<>dir THEN BEEP .07,5: LET odir=dir
   95 LET z$=SCREEN$ (l,c): IF z$="#" OR z$="O" THEN BEEP .5,33: FOR q=1 TO 5: BEEP .1,-44: NEXT q: GO TO 170
  100 IF z$="^" THEN LET sc=sc+1*(1+liv): BEEP .03,5: BEEP .03,9
  105 IF z$="@" THEN LET sc=sc+1*(1+liv): BEEP .03,0: BEEP .03,3: BEEP .03,5: BEEP .03,7: BEEP .03,9
  110 IF z$="*" THEN LET sc=sc+3*(1+liv): BEEP .03,0: BEEP .03,5: BEEP .03,9
  115 LET k=k+1: LET a$(1,k)=CHR$ l: LET a$(2,k)=CHR$ c: RETURN 
  120 IF RND<.7 THEN RETURN 
  125 LET n=INT (19*RND)+1: LET m=INT (RND*29)+1: LET z$=SCREEN$ (n,m): IF z$<>" " THEN GO TO 145
  130 IF RND>.3 THEN PRINT INK 4;AT n,m;"^": RETURN 
  135 IF RND>.1 THEN PRINT INK 6;AT n,m;"*": RETURN 
  140 PRINT INK 3;AT n,m;"@": BEEP .01,13: RETURN 
  145 IF z$="O" OR z$="#" THEN RETURN 
  150 PRINT AT n,m;" ": RETURN 
  155 LET long=long+RND: FOR q=1 TO INT (g)
  160 LET n=INT (18*RND)+2: LET m=INT (29*RND)+1: IF SCREEN$ (n,m)="#" OR SCREEN$ (n,m)="O" THEN GO TO 160
  165 BEEP .1,7: BEEP .1,9: PRINT BRIGHT 1; INK 2;AT n,m;"#": NEXT q: BRIGHT 0: RETURN 
  170 LET zz=zz+1: LET liv=liv-1: IF liv>0 THEN GO TO 265
  175 CLS : RESTORE 9999: PRINT INK 4;"You are dead! Your score= ";sc: FOR i=1 TO 11: READ a,b: BEEP a,b: NEXT i
  180 FOR i=1 TO 10: IF sc>a(i) THEN GO TO 190
  185 NEXT i: GO TO 200
  190 FOR k=10 TO i STEP -1: LET a(k+1)=a(k): LET p$(k+1, TO )=p$(k, TO ): NEXT k
  195 PRINT INK 4;"Your score= ";sc;" & is # ";i;"!": PRINT "Key in your 3 initials & press ENTER.": POKE 23658,8: INPUT LINE p$(i): LET a(i)=sc: POKE 23658,0
  200 PRINT INK 6;TAB 9;"TOP 10": FOR i=1 TO 10: LET z$=STR$ i: PRINT INK 6;TAB (10-LEN z$);i;".";p$(i);".....";a(i): NEXT i: PRINT INK 5;''"Press("; FLASH 1;"P"; FLASH 0;")lay OR ("; FLASH 1;"Q"; FLASH 0;")uit."
  205 LET z$=INKEY$: IF z$="P" OR z$="p" THEN GO TO 220
  210 IF z$="Q" OR z$="q" THEN ON ERR RESET : STOP 
  215 GO TO 205
  220 PAPER 0: LET liv=5: LET sc=0: INK 5: BORDER 0: CLS : PRINT TAB 12; FLASH 1;"WORM"; FLASH 0: PRINT ''TAB 3;"Everybody loves to play WORM!"
  225 PRINT '"In WORM, you are an ever growing& always hungry centapede."'"You move around the area trying not to touch the red areas or   yourself!"
  230 PRINT "To touch a red area or yourself is certain death & causes you to lose one of your lives."''"You score 1 point by landing on the "; INK 4;"^"; INK 5;"  (leaf) or 3 points for the "; INK 6;"*"; INK 5;"  (lemon)."
  235 PRINT "The "; INK 3;"@"; INK 5;" (flowers) are 5 points!"
  240 PRINT "You score bonus points accordingto the life level you are on."'"Press any key.": PAUSE 0: CLS 
  245 PRINT '''"You may use the arrow keys or a joystick. A BEEP will sound to "'"let you know your move has been registered."
  250 PRINT '"If you do not turn, you continuein the direction you were going."''"Good Luck! & Happy eating!"''"Press 1 for the keyboard."'"Press 0 for the joystick."
  255 LET j=CODE INKEY$-48: IF j<0 OR j>1 THEN GO TO 255
  260 CLS : LET zz=0: LET long =3: LET k=1: LET l=k: LET c=k: LET cnt=zz: LET dir=long-k: LET g=-13: DIM a$(2,630): LET odir=dir: FOR i=l TO dir: LET a$(1,i)=CHR$ i: LET a$(2,i)=CHR$ i: NEXT i: GO TO 10
  265 CLS : PRINT INK 5;'''"You got killed!"''"Your score= ";sc''"Only ";liv;" live(s) left!"''"Press a key or fire button."
  270 IF |(2,1)=1 OR INKEY$<>"" THEN GO TO 260
  275 GO TO 270
 9982 SAVE "WORM.B1" LINE 1
 9983 GO TO 9982
 9992 SAVE "WORM.B1" LINE 1
 9998 REM  was LKDOS-only
 9999 DATA .75,4,.75,4,.2,4,.75,4,.3,6,.75,6,.2,4,.6,4,.3,3,.7,4,.74,4

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.