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 ERRandSTICKkeywords. POKE 23658,8turns 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 CONTINUEto 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.
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,4Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.


