Eating changes one part of an ordinary move: the tail stays put. The head still advances, so the body gains one cell.
This first challenge has one fixed snack at row 8, column 12. Reach it to finish. FOOD should become 1/1 and LENGTH should become 5.
Replace lines 130, 300, 1020, 7000.
Add lines 330, 380, 420, 430, 440, 450, 2000, 2020, 2030, 2500, 2510, 7260.
130 GO SUB 1000: GO SUB 2000: GO SUB 2500
300 LET grow=(nr=fr AND nx=fc)
330 IF grow=1 THEN GO TO 380
380 LET n=n+1: LET eaten=eaten+1
420 IF grow=0 THEN GO TO 460
430 GO SUB 2500
440 IF eaten=1 THEN LET e$="One snack. Nicely done!": GO TO 4000
450 GO SUB 2000
1020 PRINT AT 2,5; INK 7;"Eat one snack. R retries."
2000 LET fr=8: LET fc=12
2020 PRINT AT fr+3,fc+3; INK 6;CHR$ 150
2030 RETURN
2500 PRINT AT 1,4; INK 7;"FOOD ";eaten;"/1";AT 1,18;"LENGTH ";n;" "
2510 RETURN
7000 RESTORE 7200: FOR j=0 TO 55: READ v: POKE USR "a"+j,v: NEXT j: RETURN
7260 DATA 8,16,60,126,94,126,60,0RUN the changed program.
Complete source at this checkpoint
10 GO SUB 7000
100 DIM a(12): DIM b(12)
110 LET n=4: LET eaten=0: LET h=4: LET t=1: LET dr=0: LET dc=1: LET steps=0
120 FOR j=1 TO 4: LET a(j)=8: LET b(j)=j+5: NEXT j
130 GO SUB 1000: GO SUB 2000: GO SUB 2500
140 LET nd=dr: LET nc=dc: LET turn=0: LET tick=PEEK 23672
150 LET k$=INKEY$
160 IF k$="q" OR k$="Q" THEN GO TO 9000
170 IF k$="r" OR k$="R" THEN GO TO 100
180 IF turn=1 THEN GO TO 240
190 IF (k$="i" OR k$="I") AND dr=0 THEN LET nd=-1: LET nc=0: LET turn=1
200 IF (k$="k" OR k$="K") AND dr=0 THEN LET nd=1: LET nc=0: LET turn=1
210 IF (k$="j" OR k$="J") AND dc=0 THEN LET nd=0: LET nc=-1: LET turn=1
220 IF (k$="l" OR k$="L") AND dc=0 THEN LET nd=0: LET nc=1: LET turn=1
240 LET elapsed=PEEK 23672 -tick
250 IF elapsed<0 THEN LET elapsed=elapsed+256
260 IF elapsed<18 THEN GO TO 150
270 LET tick=PEEK 23672: LET dr=nd: LET dc=nc
280 LET nr=a(h)+dr: LET nx=b(h)+dc
290 IF nr<1 OR nr>16 OR nx<1 OR nx>24 THEN LET e$="Mind the wall!": GO TO 4000
300 LET grow=(nr=fr AND nx=fc)
310 GO SUB 3500: IF hit=1 THEN LET e$="You caught your tail!": GO TO 4000
320 PRINT AT a(h)+3,b(h)+3; INK 5;CHR$ 149
330 IF grow=1 THEN GO TO 380
340 PRINT AT a(t)+3,b(t)+3;" "
350 LET t=t+1: IF t=13 THEN LET t=1
360 GO TO 390
380 LET n=n+1: LET eaten=eaten+1
390 LET h=h+1: IF h=13 THEN LET h=1
400 LET a(h)=nr: LET b(h)=nx: LET steps=steps+1
410 GO SUB 3000
420 IF grow=0 THEN GO TO 460
430 GO SUB 2500
440 IF eaten=1 THEN LET e$="One snack. Nicely done!": GO TO 4000
450 GO SUB 2000
460 LET nd=dr: LET nc=dc: LET turn=0: GO TO 150
1000 BORDER 0: PAPER 0: INK 7: CLS
1010 PRINT AT 0,11; INK 5;"TAIL CHASE"
1020 PRINT AT 2,5; INK 7;"Eat one snack. R retries."
1030 FOR x=3 TO 28: PRINT AT 3,x; INK 1;CHR$ 144;AT 20,x;CHR$ 144: NEXT x
1040 FOR y=4 TO 19: PRINT AT y,3; INK 1;CHR$ 144;AT y,28;CHR$ 144: NEXT y
1050 FOR j=1 TO 4: PRINT AT a(j)+3,b(j)+3; INK 5;CHR$ 149: NEXT j
1060 GO SUB 3000
1070 PRINT AT 21,1; INK 5;"I J K L steer R retry Q quit";
1080 RETURN
2000 LET fr=8: LET fc=12
2020 PRINT AT fr+3,fc+3; INK 6;CHR$ 150
2030 RETURN
2500 PRINT AT 1,4; INK 7;"FOOD ";eaten;"/1";AT 1,18;"LENGTH ";n;" "
2510 RETURN
3000 LET z=146
3010 IF dr=-1 THEN LET z=145
3020 IF dr=1 THEN LET z=147
3030 IF dc=-1 THEN LET z=148
3040 PRINT AT a(h)+3,b(h)+3; INK 7;CHR$ z
3050 RETURN
3500 LET hit=0: LET slot=t
3510 FOR j=1 TO n
3520 IF j=1 AND grow=0 THEN GO TO 3540
3530 IF a(slot)=nr AND b(slot)=nx THEN LET hit=1
3540 LET slot=slot+1: IF slot=13 THEN LET slot=1
3550 NEXT j: RETURN
4000 PRINT AT 2,0;" ";AT 2,2; INK 6;e$
4010 PRINT AT 21,1; INK 7;"R for another go Q to quit ";
4020 IF INKEY$<>"" THEN GO TO 4020
4030 LET k$=INKEY$
4040 IF k$="q" OR k$="Q" THEN GO TO 9000
4050 IF k$="r" OR k$="R" THEN GO TO 100
4060 GO TO 4030
7000 RESTORE 7200: FOR j=0 TO 55: READ v: POKE USR "a"+j,v: NEXT j: RETURN
7200 DATA 255,129,129,129,255,129,129,255
7210 DATA 60,126,90,90,126,126,60,24
7220 DATA 60,126,252,204,204,252,126,60
7230 DATA 24,60,126,126,90,90,126,60
7240 DATA 60,126,63,51,51,63,126,60
7250 DATA 0,60,126,126,126,126,60,0
7260 DATA 8,16,60,126,94,126,60,0
9000 PAPER 0: INK 7: PRINT AT 21,0;"Finished. RUN to try again. ";: STOPRecognise food before changing the body
Line 300 compares the proposed head with fr,fc, the food coordinates. Sinclair BASIC comparisons produce 1 for true and 0 for false. grow therefore records whether this move eats the food.
For an ordinary move, erase the tail and advance t. For a growing move, line 330 skips that work. Line 380 increases n and eaten, then the shared code advances h and stores the new head. This is the circular array’s growing case: keep the oldest position while appending a new one.
The collision scan must now distinguish both cases. Skip its first live cell only when grow is zero. If the tail stays, its square remains occupied.

Draw the snack and its progress
The fruit is code 150, with row bytes 8,16,60,126,94,126,60,0. The first two rows make the stalk; the rounded lower rows and small gap distinguish the fruit from the body. It is yellow, but its shape also carries its identity. The loader now installs seven characters, 56 bytes in total.
The food routine sets the fixed coordinates and draws it. The HUD routine prints FOOD and LENGTH on the reserved row. Updating that row after eating changes the progress display without redrawing the arena. This challenge ends after one food, so there is no replacement food yet.
Check a longer body’s collision
At length four, the departing-tail case makes a tight loop legal. To test an occupied square that will remain occupied, use this temporary diagnostic. It changes only the instruction and the result after eating. The food coordinates become (0,0), outside the arena, so no further move can eat another snack.
Replace lines 440, 1020.
440 LET fr=0: LET fc=0: GO TO 460
1020 PRINT AT 2,2; INK 7;"Body test: eat, then turn."RUN the changed program.
Complete source at this checkpoint
10 GO SUB 7000
100 DIM a(12): DIM b(12)
110 LET n=4: LET eaten=0: LET h=4: LET t=1: LET dr=0: LET dc=1: LET steps=0
120 FOR j=1 TO 4: LET a(j)=8: LET b(j)=j+5: NEXT j
130 GO SUB 1000: GO SUB 2000: GO SUB 2500
140 LET nd=dr: LET nc=dc: LET turn=0: LET tick=PEEK 23672
150 LET k$=INKEY$
160 IF k$="q" OR k$="Q" THEN GO TO 9000
170 IF k$="r" OR k$="R" THEN GO TO 100
180 IF turn=1 THEN GO TO 240
190 IF (k$="i" OR k$="I") AND dr=0 THEN LET nd=-1: LET nc=0: LET turn=1
200 IF (k$="k" OR k$="K") AND dr=0 THEN LET nd=1: LET nc=0: LET turn=1
210 IF (k$="j" OR k$="J") AND dc=0 THEN LET nd=0: LET nc=-1: LET turn=1
220 IF (k$="l" OR k$="L") AND dc=0 THEN LET nd=0: LET nc=1: LET turn=1
240 LET elapsed=PEEK 23672 -tick
250 IF elapsed<0 THEN LET elapsed=elapsed+256
260 IF elapsed<18 THEN GO TO 150
270 LET tick=PEEK 23672: LET dr=nd: LET dc=nc
280 LET nr=a(h)+dr: LET nx=b(h)+dc
290 IF nr<1 OR nr>16 OR nx<1 OR nx>24 THEN LET e$="Mind the wall!": GO TO 4000
300 LET grow=(nr=fr AND nx=fc)
310 GO SUB 3500: IF hit=1 THEN LET e$="You caught your tail!": GO TO 4000
320 PRINT AT a(h)+3,b(h)+3; INK 5;CHR$ 149
330 IF grow=1 THEN GO TO 380
340 PRINT AT a(t)+3,b(t)+3;" "
350 LET t=t+1: IF t=13 THEN LET t=1
360 GO TO 390
380 LET n=n+1: LET eaten=eaten+1
390 LET h=h+1: IF h=13 THEN LET h=1
400 LET a(h)=nr: LET b(h)=nx: LET steps=steps+1
410 GO SUB 3000
420 IF grow=0 THEN GO TO 460
430 GO SUB 2500
440 LET fr=0: LET fc=0: GO TO 460
450 GO SUB 2000
460 LET nd=dr: LET nc=dc: LET turn=0: GO TO 150
1000 BORDER 0: PAPER 0: INK 7: CLS
1010 PRINT AT 0,11; INK 5;"TAIL CHASE"
1020 PRINT AT 2,2; INK 7;"Body test: eat, then turn."
1030 FOR x=3 TO 28: PRINT AT 3,x; INK 1;CHR$ 144;AT 20,x;CHR$ 144: NEXT x
1040 FOR y=4 TO 19: PRINT AT y,3; INK 1;CHR$ 144;AT y,28;CHR$ 144: NEXT y
1050 FOR j=1 TO 4: PRINT AT a(j)+3,b(j)+3; INK 5;CHR$ 149: NEXT j
1060 GO SUB 3000
1070 PRINT AT 21,1; INK 5;"I J K L steer R retry Q quit";
1080 RETURN
2000 LET fr=8: LET fc=12
2020 PRINT AT fr+3,fc+3; INK 6;CHR$ 150
2030 RETURN
2500 PRINT AT 1,4; INK 7;"FOOD ";eaten;"/1";AT 1,18;"LENGTH ";n;" "
2510 RETURN
3000 LET z=146
3010 IF dr=-1 THEN LET z=145
3020 IF dr=1 THEN LET z=147
3030 IF dc=-1 THEN LET z=148
3040 PRINT AT a(h)+3,b(h)+3; INK 7;CHR$ z
3050 RETURN
3500 LET hit=0: LET slot=t
3510 FOR j=1 TO n
3520 IF j=1 AND grow=0 THEN GO TO 3540
3530 IF a(slot)=nr AND b(slot)=nx THEN LET hit=1
3540 LET slot=slot+1: IF slot=13 THEN LET slot=1
3550 NEXT j: RETURN
4000 PRINT AT 2,0;" ";AT 2,2; INK 6;e$
4010 PRINT AT 21,1; INK 7;"R for another go Q to quit ";
4020 IF INKEY$<>"" THEN GO TO 4020
4030 LET k$=INKEY$
4040 IF k$="q" OR k$="Q" THEN GO TO 9000
4050 IF k$="r" OR k$="R" THEN GO TO 100
4060 GO TO 4030
7000 RESTORE 7200: FOR j=0 TO 55: READ v: POKE USR "a"+j,v: NEXT j: RETURN
7200 DATA 255,129,129,129,255,129,129,255
7210 DATA 60,126,90,90,126,126,60,24
7220 DATA 60,126,252,204,204,252,126,60
7230 DATA 24,60,126,126,90,90,126,60
7240 DATA 60,126,63,51,51,63,126,60
7250 DATA 0,60,126,126,126,126,60,0
7260 DATA 8,16,60,126,94,126,60,0
9000 PAPER 0: INK 7: PRINT AT 21,0;"Finished. RUN to try again. ";: STOPLet the head eat the fixed food while moving right. Then turn down, left and up on consecutive moves. The last turn should produce You caught your tail! without moving the head into the body. R restores the four-cell starting state. This diagnostic continues after the snack deliberately; the next lesson restores the one-food ending.
Why is adding one to n insufficient to make the snake grow?
Show the explanation
If the tail were still removed, only four positions would remain live while n claimed there were five. Growth must preserve the tail as well as increasing the count.
Revisit: what does growth preserve?
Return to the saved unit 5 copy and this lesson’s normal one-food copy. Let both travel right for three moves. Before running, write down their expected bodies after move two, then after move three. The starting head is at (8,9); the food in this lesson is at (8,12).
Hint: keep or discard the oldest pair?
After move two, both bodies run from (8,8) to (8,11). An ordinary move drops (8,8). An eating move keeps it. Both append (8,12).
Explain the difference
Unit 5 still has four cells, (8,9) through (8,12), in slots 4–7. Unit 6 has five cells, (8,8) through (8,12), in slots 3–7, and stops at its one-food result. Both have h=7, but their tails and lengths differ. This is an intentional rule change, not evidence that the representation comparison failed.
Use this lesson’s clearly labelled second checkpoint for the next test. Predict the down/left/up route after eating before trying it. On the final up move the candidate is (8,11), a body square that remains occupied; the body must stay unchanged when the move is rejected. Explain why the same tight turn can succeed at length four. Then retry twice and check that each new start has four cells, tail slot 1, head slot 4 and no food eaten.
We can now explain two separate changes: unit 5 preserves the rules while changing storage; unit 6 uses that storage to add growth. Keep the normal one-food copy as the baseline. The diagnostic’s continued play is only for investigating collision.
Sources
Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), 3 (comparisons), 12 (arrays) and 14 (characters).
Run it here
This unit's program, built for you.
- Program
- step-02.tap
- Machine
- ZX Spectrum 48K (PAL)