Skip to content

Choose the next turn

Queue one perpendicular turn per move and draw the matching face.

  • Sinclair ZX Spectrum
  • BASIC

A direction key requests the next turn. It does not supply the movement itself: the clock keeps advancing the head.

Use I up, J left, K down and L right. R retries and Q quits. Press one direction at a time.

Delete line 7010.

Replace lines 140, 270, 460, 1070, 7000.

Add lines 180, 190, 200, 210, 220, 3010, 3020, 3030, 7210, 7230, 7240.

Delete a BASIC line by entering its number on its own. Do not type a deletion marker into the program.

step-01-edits.bas
 140 LET nd=dr: LET nc=dc: LET turn=0: LET tick=PEEK 23672
 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
 270 LET tick=PEEK 23672: LET dr=nd: LET dc=nc
 460 LET nd=dr: LET nc=dc: LET turn=0: GO TO 150
1070 PRINT AT 21,1; INK 5;"I J K L steer  R retry  Q quit";
3010 IF dr=-1 THEN LET z=145
3020 IF dr=1 THEN LET z=147
3030 IF dc=-1 THEN LET z=148
7000 RESTORE 7200: FOR j=0 TO 39: READ v: POKE USR "a"+j,v: NEXT j: RETURN
7210 DATA 60,126,90,90,126,126,60,24
7230 DATA 24,60,126,126,90,90,126,60
7240 DATA 60,126,63,51,51,63,126,60

RUN the changed program.

Complete source at this checkpoint
step-01.bas
  10 GO SUB 7000
 110 LET r=8: LET c=9: LET dr=0: LET dc=1: LET steps=0
 130 GO SUB 1000
 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 110
 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=r+dr: LET nx=c+dc
 290 IF nr<1 OR nr>16 OR nx<1 OR nx>24 THEN LET e$="Mind the wall!": GO TO 4000
 400 PRINT AT r+3,c+3;" ": LET r=nr: LET c=nx: LET steps=steps+1
 410 GO SUB 3000
 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;"Keep some room to 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
1060 GO SUB 3000
1070 PRINT AT 21,1; INK 5;"I J K L steer  R retry  Q quit";
1080 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 r+3,c+3; INK 7;CHR$ z
3050 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 110
4060 GO TO 4030
7000 RESTORE 7200: FOR j=0 TO 39: 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
9000 PAPER 0: INK 7: PRINT AT 21,0;"Finished. RUN to try again.     ";: STOP

Two directions, one decision

dr,dc describe the current heading. nd,nc hold the pending heading. For example, moving right is (0,1), while turning up requests (−1,0). Rows grow downwards, so up subtracts from the row.

While moving horizontally, dr=0, so the program can accept I or K. While moving vertically, dc=0, so it can accept J or L. Continuing in the same direction needs no change. The opposite direction is ignored; soon there will be a neck behind the head.

The first accepted perpendicular turn sets turn=1. Line 180 then skips further direction requests until movement occurs. R and Q are checked before this lock, so they still work. At line 270 the pending direction becomes current; line 460 clears the lock for the following move.

Without that lock, a quick up-then-left request while travelling right could turn through two directions before the head moved, effectively reversing it. We accept one turn for one movement update.

Show the heading

The graphic DATA now fills five consecutive characters: wall, up head, right head, down head and left head. The head routine starts with code 146 for right, then selects 145 for up, 147 for down or 148 for left. These are character codes, distinct from the eight row bytes that draw each face. The other faces use the same rounded outline with the eye pixels facing the relevant direction; compare their DATA rows before changing them.

Moving right, you request up and then left before the next move. Which square should the head enter?

Show the explanation

The square above it. Up is the first perpendicular request and locks the pending turn. Left must wait for a later update.

Try a long hold, a short tap, an unrelated key and an opposite direction. INKEY$ reports a key when the program reads it; it does not store every tap made between reads. With multiple ordinary keys held, do not expect a direction chord. Hold one key at a time and check that turning remains predictable.

Sources

Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), 14 (characters) and 18 (keyboard input).

Run it here

This unit's program, built for you.

Program
step-01.tap
Machine
ZX Spectrum 48K (PAL)

Download step-01.tap