The head should move whether or not a key is down. This checkpoint travels right until it reaches the wall. R starts again and Q returns to BASIC.
Delete lines 20, 30, 40.
Replace line 1070.
Add lines 110, 130, 140, 150, 160, 170, 240, 250, 260, 270, 280, 290, 400, 410, 460, 4000, 4010, 4020, 4030, 4040, 4050, 4060.
Delete a BASIC line by entering its number on its own. Do not type a deletion marker into the program.
110 LET r=8: LET c=9: LET dr=0: LET dc=1: LET steps=0
130 GO SUB 1000
140 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
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
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 GO TO 150
1070 PRINT AT 21,7; INK 5;"R retry Q quit";
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 4030RUN the changed program.
Complete source at this checkpoint
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 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
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
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 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,7; INK 5;"R retry Q quit";
1080 RETURN
3000 LET z=146
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 7: READ v: POKE USR "a"+j,v: NEXT j
7010 RESTORE 7220: FOR j=0 TO 7: READ v: POKE USR "c"+j,v: NEXT j: RETURN
7200 DATA 255,129,129,129,255,129,129,255
7220 DATA 60,126,252,204,204,252,126,60
9000 PAPER 0: INK 7: PRINT AT 21,0;"Finished. RUN to try again. ";: STOPPropose, check, then draw
Line 110 starts at row 8, column 9. dr=0 and dc=1 mean no row change and one column to the right. Line 280 computes nr and nx, the proposed next row and column. It has not moved the head yet.
Line 290 rejects coordinates outside rows 1–16 or columns 1–24. The result routine displays the wall message and waits for R or Q. A rejected move leaves the last valid head visible.
For an accepted move, line 400 erases the old cell and stores the new coordinates. The routine at 3000 draws the head there. Only the changing cells need drawing; clearing the whole screen on every move would redraw walls that have not changed.
Wait while checking keys
PEEK 23672 reads the lowest byte of the Spectrum’s FRAMES counter. In this PAL configuration it advances fifty times per second during ordinary program execution. The program stores a reading in tick, then subtracts it from a later reading. While fewer than 18 ticks have elapsed, it returns to line 150 and checks keys again.
That byte counts from 0 to 255 and then returns to zero. If tick was 250 and the new reading is 5, the subtraction gives −245. Adding 256 gives 11 elapsed ticks. Line 250 makes this correction. The method assumes we sample again before 256 ticks have elapsed; it is not a general clock for long pauses.
The threshold is a minimum wait, not a promise of one move every 18 ticks. BASIC still has input, decisions and drawing to perform. Line 270 records the next starting time before that movement work. If the work takes longer, the program cannot recover the lost time by pretending it was faster. Tape operations and BEEP also affect this ROM clock; this game’s moving loop is silent and does neither.
Does reaching 18 ticks mean the head has already been drawn at its new position?
Show the explanation
No. It permits the program to leave the waiting loop. The candidate calculation, boundary check and drawing follow it.
Run without touching the keyboard: the head should stop at the right edge. Retry, then hold Q. If the wall message instantly disappears on a retry attempt, release all keys first: the result routine deliberately waits for release before accepting a new R or Q.
Sources
Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), 18, pp. 129–131 (FRAMES and keyboard input), and chapters 4–5 (loops and routines).
Run it here
This unit's program, built for you.
- Program
- step-01.tap
- Machine
- ZX Spectrum 48K (PAL)