We can see the target, so there is no mystery yet. That makes this a useful moment to check whether a chosen coordinate reaches the right cell.
Ask for one coordinate
Continue from the complete board. First make the row prompt work on its own.
Delete lines 90. Enter each line number on its own, then press Enter.
Replace lines 10, 80, 100.
Add lines 60, 70, 110, 115, 3000, 3010, 3015, 3020, 3030, 3040, 3050, 3060, 3100, 3110, 4000, 4010, 4020, 4030, 4040, 4050, 4070, 4080, 9000, 9010.
10 LET stage=2
60 LET lr=0: LET lc=0
70 PAPER 0: INK 7
80 PRINT AT 21,0;"Row then column. Q quits.";
100 LET p$="Row": GO SUB 3000: LET pr=v
110 PRINT AT 21,0;"Selected row: ";pr;" ";
115 GO TO 100
3000 PAPER 0: INK 7
3010 INPUT (p$+" (1-8, Q): "); LINE a$
3015 IF LEN a$>16 THEN GO SUB 4000
3020 IF a$="q" OR a$="Q" THEN GO TO 9000
3030 IF LEN a$<>1 THEN GO TO 3100
3040 IF a$<"1" OR a$>"8" THEN GO TO 3100
3050 LET v=VAL a$
3060 RETURN
3100 PRINT AT 21,0;"Use one digit from 1 to 8. ";
3110 GO TO 3010
4000 GO SUB 1000
4010 LET r=tr: LET c=tc: GO SUB 2000
4020 PRINT AT y,x;" X "
4030 IF lr=0 THEN GO TO 4070
4040 LET r=lr: LET c=lc: GO SUB 2000
4050 PRINT AT y,x;">";b$
4070 PAPER 0: INK 7
4080 RETURN
9000 PRINT AT 21,0;"Finished. RUN to try again. ";
9010 STOPComplete program for this step
10 LET stage=2
20 LET tr=3: LET tc=6
30 GO SUB 1000
40 LET r=tr: LET c=tc: GO SUB 2000
50 PRINT AT y,x;" X "
60 LET lr=0: LET lc=0
70 PAPER 0: INK 7
80 PRINT AT 21,0;"Row then column. Q quits.";
100 LET p$="Row": GO SUB 3000: LET pr=v
110 PRINT AT 21,0;"Selected row: ";pr;" ";
115 GO TO 100
1000 BORDER 1: PAPER 0: INK 7: CLS
1010 PRINT AT 0,9;"SONAR - STAGE ";stage
1020 FOR c=1 TO 8
1030 PRINT AT 2,6 +3 *(c-1);c
1040 NEXT c
1050 PRINT AT 3,4;"+------------------------+"
1060 PRINT AT 20,4;"+------------------------+"
1070 FOR r=1 TO 8
1080 PRINT AT 4 +2 *(r-1),2;r
1090 FOR k=0 TO 1
1100 PRINT AT 4 +2 *(r-1)+k,4;":";AT 4 +2 *(r-1)+k,29;":"
1110 NEXT k
1120 FOR c=1 TO 8
1130 GO SUB 2000
1140 PRINT AT y,x;" . ";AT y+1,x;" "
1150 NEXT c
1160 PAPER 0: INK 7
1170 NEXT r
1180 RETURN
2000 LET y=4 +2 *(r-1): LET x=5 +3 *(c-1)
2010 PAPER 1: INK 7
2020 IF r+c=2 *INT ((r+c)/2) THEN PAPER 5: INK 0
2030 RETURN
3000 PAPER 0: INK 7
3010 INPUT (p$+" (1-8, Q): "); LINE a$
3015 IF LEN a$>16 THEN GO SUB 4000
3020 IF a$="q" OR a$="Q" THEN GO TO 9000
3030 IF LEN a$<>1 THEN GO TO 3100
3040 IF a$<"1" OR a$>"8" THEN GO TO 3100
3050 LET v=VAL a$
3060 RETURN
3100 PRINT AT 21,0;"Use one digit from 1 to 8. ";
3110 GO TO 3010
4000 GO SUB 1000
4010 LET r=tr: LET c=tc: GO SUB 2000
4020 PRINT AT y,x;" X "
4030 IF lr=0 THEN GO TO 4070
4040 LET r=lr: LET c=lc: GO SUB 2000
4050 PRINT AT y,x;">";b$
4070 PAPER 0: INK 7
4080 RETURN
9000 PRINT AT 21,0;"Finished. RUN to try again. ";
9010 STOPp$ holds the prompt label and a$ holds the answer. Sinclair BASIC string names are a single letter followed by $. INPUT LINE reads the answer as text, so an expression such as 1+1 is not evaluated. The + between strings joins them into one prompt.
The routine at 3000 puts the screen colours back to black paper and white ink before asking. It accepts lowercase or uppercase Q using OR: either comparison is enough to leave. LEN gives the number of characters. We require one character, then compare it with the strings "1" and "8". Only after those checks does VAL convert the digit into a number. v is the routine’s result; line 100 copies it into pr, the probe row.
Wrong input jumps to the message at 3100 and returns to the same prompt. GO TO transfers control without remembering a return address, unlike GO SUB. The main loop displays the selected row and asks again. Try an empty answer, 0, 9, a letter and 1.5, then enter 5.
Use the same routine twice
Delete lines 115. Enter each line number on its own, then press Enter.
Replace lines 110.
Add lines 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270.
110 LET p$="Column": GO SUB 3000: LET pc=v
120 IF lr=0 THEN GO TO 160
130 LET r=lr: LET c=lc: GO SUB 2000
140 PRINT AT y,x;" . "
150 IF r=tr AND c=tc THEN PRINT AT y,x;" X "
160 LET r=pr: LET c=pc: GO SUB 2000
170 LET d=1
180 IF r=tr AND c=tc THEN LET d=0
190 LET b$=" -"
200 IF d=0 THEN LET b$=" *"
210 PRINT AT y,x;">";b$
220 LET lr=r: LET lc=c
230 PAPER 0: INK 7
240 PRINT AT 21,0;" ";
250 IF d<>0 THEN PRINT AT 21,0;"Miss. Try another cell.";
260 IF d=0 THEN PRINT AT 21,0;"Found! Q quits; RUN tries again";
270 GO TO 100Complete program for this step
10 LET stage=2
20 LET tr=3: LET tc=6
30 GO SUB 1000
40 LET r=tr: LET c=tc: GO SUB 2000
50 PRINT AT y,x;" X "
60 LET lr=0: LET lc=0
70 PAPER 0: INK 7
80 PRINT AT 21,0;"Row then column. Q quits.";
100 LET p$="Row": GO SUB 3000: LET pr=v
110 LET p$="Column": GO SUB 3000: LET pc=v
120 IF lr=0 THEN GO TO 160
130 LET r=lr: LET c=lc: GO SUB 2000
140 PRINT AT y,x;" . "
150 IF r=tr AND c=tc THEN PRINT AT y,x;" X "
160 LET r=pr: LET c=pc: GO SUB 2000
170 LET d=1
180 IF r=tr AND c=tc THEN LET d=0
190 LET b$=" -"
200 IF d=0 THEN LET b$=" *"
210 PRINT AT y,x;">";b$
220 LET lr=r: LET lc=c
230 PAPER 0: INK 7
240 PRINT AT 21,0;" ";
250 IF d<>0 THEN PRINT AT 21,0;"Miss. Try another cell.";
260 IF d=0 THEN PRINT AT 21,0;"Found! Q quits; RUN tries again";
270 GO TO 100
1000 BORDER 1: PAPER 0: INK 7: CLS
1010 PRINT AT 0,9;"SONAR - STAGE ";stage
1020 FOR c=1 TO 8
1030 PRINT AT 2,6 +3 *(c-1);c
1040 NEXT c
1050 PRINT AT 3,4;"+------------------------+"
1060 PRINT AT 20,4;"+------------------------+"
1070 FOR r=1 TO 8
1080 PRINT AT 4 +2 *(r-1),2;r
1090 FOR k=0 TO 1
1100 PRINT AT 4 +2 *(r-1)+k,4;":";AT 4 +2 *(r-1)+k,29;":"
1110 NEXT k
1120 FOR c=1 TO 8
1130 GO SUB 2000
1140 PRINT AT y,x;" . ";AT y+1,x;" "
1150 NEXT c
1160 PAPER 0: INK 7
1170 NEXT r
1180 RETURN
2000 LET y=4 +2 *(r-1): LET x=5 +3 *(c-1)
2010 PAPER 1: INK 7
2020 IF r+c=2 *INT ((r+c)/2) THEN PAPER 5: INK 0
2030 RETURN
3000 PAPER 0: INK 7
3010 INPUT (p$+" (1-8, Q): "); LINE a$
3015 IF LEN a$>16 THEN GO SUB 4000
3020 IF a$="q" OR a$="Q" THEN GO TO 9000
3030 IF LEN a$<>1 THEN GO TO 3100
3040 IF a$<"1" OR a$>"8" THEN GO TO 3100
3050 LET v=VAL a$
3060 RETURN
3100 PRINT AT 21,0;"Use one digit from 1 to 8. ";
3110 GO TO 3010
4000 GO SUB 1000
4010 LET r=tr: LET c=tc: GO SUB 2000
4020 PRINT AT y,x;" X "
4030 IF lr=0 THEN GO TO 4070
4040 LET r=lr: LET c=lc: GO SUB 2000
4050 PRINT AT y,x;">";b$
4070 PAPER 0: INK 7
4080 RETURN
9000 PRINT AT 21,0;"Finished. RUN to try again. ";
9010 STOPThe first call sets p$ to Row and stores pr. The second sets it to Column and stores pc. An invalid column does not repeat the row prompt. Both coordinates are valid before the game uses them.
For this first test, d=1 means a miss and d=0 means a hit. The AND in line 180 requires both row and column to match the target. b$ holds the two characters to print: a space and either a dash or an asterisk. Printing > before them identifies the latest probe.
lr and lc remember the last probe position. Zero means that no probe has happened yet. On the next turn, lines 120–150 erase that old marker, restoring the X if necessary. This version remembers only one probe; losing older results will soon give us a reason to store more.
Protect the display
The ROM normally uses the bottom of the screen for input. A very long answer can make that area expand and scroll the game. Line 3015 calls the recovery routine at 4000 after answers longer than sixteen characters. It redraws the board, target and latest probe before the validation error appears. It does not accept a long answer as a coordinate.
The status line is screen row 21, above the usual input area. Its PRINT statements end in a semicolon to avoid advancing beyond that row. Blank spaces remove any longer previous message. PAPER 0: INK 7 restores the message colours after drawing a cell.
Why not call VAL as soon as the player presses Enter?
Show the explanation
The answer could be Q, empty text or an expression. We first decide whether it is a permitted coordinate. Only one digit from 1 to 8 reaches VAL, so conversion cannot interpret an unwanted expression.
Try row 1, column 2 for a miss, then row 3, column 6 for a hit. A hit does not end this diagnostic version: you can continue checking cells or enter Q. Test Q at both prompts, and test a long invalid answer after a probe. Use RUN to start again.
Sources
Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapters 5, 7–8 and 13 (routines, strings, conversion and conditions), and 15 (INPUT LINE and the input area).
Run it here
This unit's program, built for you.
- Program
- step-02.tap
- Machine
- ZX Spectrum 48K (PAL)