Skip to content

A sea to search

Draw a labelled board and translate game coordinates into screen positions.

  • Sinclair ZX Spectrum
  • BASIC

One object is waiting beneath the sea. We will find it by sending probes to different squares and comparing their clues. First, give the search somewhere to happen.

Use a 48K ZX Spectrum with Sinclair BASIC. Save any program you want to keep before entering NEW. The Spectrum editor enters keywords as tokens; in Original keyboard mode, R enters RUN at the start of a command. Use the mode described in your setup guide. The spaces displayed around a keyword are part of its presentation, not extra keys to press after its token.

Start with one row

A game square will occupy three character columns and two character rows. The middle space holds its clue; the left space can hold a marker. Enter this first program.

step-01.bas
  10 BORDER 1: PAPER 0: INK 7: CLS
  20 LET r=1
  30 FOR c=1 TO 8
  40 LET y=4 +2 *(r-1): LET x=5 +3 *(c-1)
  50 PAPER 1: INK 7
  60 IF r+c=2 *INT ((r+c)/2) THEN PAPER 5: INK 0
  70 PRINT AT y,x;" . ";AT y+1,x;"   "
  80 NEXT c
  90 STOP

FOR c=1 TO 8 changes c through the eight board columns. NEXT c returns to that loop until the row is complete. r stays at 1 for now. These are board coordinates, beginning at 1. PRINT AT uses screen coordinates beginning at 0.

The expression 5 +3 *(c-1) starts at screen column 5 and advances three characters for each board column. Likewise, 4 +2 *(r-1) will leave two character rows for each board row. At board (1,1), these give screen row 4, column 5. Board (8,8) will begin at screen row 18, column 26.

PAPER sets the character background; INK sets the printed character colour. Blue is colour 1, cyan is 5, black is 0 and white is 7. BORDER sets the surrounding border, and CLS clears the display using the current paper colour. A semicolon joins PRINT items without starting a new line. The second AT fills the square’s lower half with spaces.

For the alternating colours, INT rounds down. When r+c is even, dividing it by two, taking INT and multiplying by two returns the original value. IF ... THEN chooses the cyan paper in that case. The initial blue settings run for every cell, so the previous cell’s colour cannot leak into the next.

Grow the board

Delete lines 60, 70. Enter each line number on its own, then press Enter.

Replace lines 10, 20, 30, 40, 50, 80, 90.

Add lines 100, 1000, 1010, 1020, 1030, 1040, 1050, 1060, 1070, 1080, 1090, 1100, 1110, 1120, 1130, 1140, 1150, 1160, 1170, 1180, 2000, 2010, 2020, 2030.

step-02-edits.bas
  10 LET stage=1
  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 "
  80 PAPER 0: INK 7
  90 PRINT AT 21,1;"X marks row 3, column 6.";
 100 STOP
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
Complete program for this step
step-02.bas
  10 LET stage=1
  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 "
  80 PAPER 0: INK 7
  90 PRINT AT 21,1;"X marks row 3, column 6.";
 100 STOP
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

The program now calls the board routine with GO SUB 1000. A subroutine is a named-by-line-number piece of work: BASIC remembers where to come back, and RETURN resumes just after the call. STOP prevents the main program from falling through into the drawing routines when it finishes. Its 9 STOP statement report is expected here.

Lines 1020–1040 label the columns. The outer loop beginning at 1070 visits each row; its inner loop beginning at 1120 draws the eight cells. The short k loop draws two frame characters down each side of a row. Our earlier position-and-colour calculation now lives at 2000, so both the board and the target use the same calculation.

tr=3 and tc=6 name the target’s row and column. Lines 40–50 draw its temporary X. The target is visible while we check the board, and will disappear when clues become useful.

Why do we subtract 1 before multiplying the board column by 3?

Show the explanation

Column 1 needs no displacement from screen column 5. Subtracting 1 makes its displacement zero. Without that subtraction, every square would move three characters to the right.

Run the program. Check eight labels in each direction, the frame, and the X at row 3, column 6. Temporarily change the target coordinates to each corner, predicting its screen position before running. Restore (3,6) afterwards. These two coordinates will stay fixed while we build the search.

Sources

Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapters 4–5 (loops and routines), 9 (INT), and 15–16 (screen positions and colour).

Run it here

This unit's program, built for you.

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

Download step-02.tap