Finish, replay and keep it
Explain the controls before play, restart with fresh state and save a complete game that can be reopened and shared.
The challenge works. Now make it possible for someone else to arrive, understand what to do, play again and keep a copy. Those are part of the game: a good round is not much use if its controls or ending leave the player guessing.
Continue from Grow a new round, with cap=16 restored. The target
remains a stock 48K Spectrum with keyboard and beeper. We need no external art
files: the panel arrangement, marker and four note choices are already in the
BASIC source.
Explain the controls before the first signal
Add 55 and the start-screen block at 2000–2150:
55 GO TO 2000
2000 PRINT AT 3,0;"Watch the order of the signals."
2010 PRINT AT 5,0;"Repeat it with keys 1 to 4."
2020 PRINT AT 7,0;"Wait for each cue to finish."
2030 PRINT AT 9,0;"Each round adds one choice."
2040 PRINT AT 11,0;"Complete 16 rounds to finish."
2050 PRINT AT 13,0;"Hold q to quit, even in WATCH."
2060 PRINT AT 15,0;"Release keys, then s to start."
2070 GO SUB 1600
2080 LET k$=INKEY$
2090 IF k$="" THEN GO TO 2080
2100 IF k$="q" THEN GO TO 1900
2110 IF k$<>"s" THEN GO TO 2070
2120 GO SUB 1600
2130 CLS
2140 PRINT "BRIGHT SPARK"
2150 GO TO 100
Line 55 jumps away before the board is drawn. The opening instructions can therefore use the central screen without colliding with panels. They explain the recurring action, the keys, the finishing point and how to leave. Asking players to wait for each cue also tells them the input’s actual pace.
The start loop uses the same capture-and-test approach as player input, but accepts s or q instead of a panel number. An unrelated key returns through the release routine before another attempt. Holding s waits at 2120; releasing it allows the game to begin. The press that starts a game cannot leak into its first response.
After release, CLS removes the instructions and line 2140 prints the title
again. The jump to 100 builds the board, then reaches the game initialisation
at 280–290. It must not jump to 10: that would send us through line 55 and back
to the start screen we just left.
Run it. Read the screen without starting immediately. Try an unrelated key, then s. Hold s for a moment: WATCH should begin after release. On another run, press q at the instructions to check that starting a game is optional.
Complete checkpoint with a start screen
10 BORDER 0
20 PAPER 0
30 INK 7
40 CLS
50 PRINT "BRIGHT SPARK"
55 GO TO 2000
100 LET lit=0
110 FOR p=1 TO 4
120 GO SUB 500
130 NEXT p
240 PRINT AT 2,7;"1"
250 PRINT AT 2,23;"2"
260 PRINT AT 11,7;"3"
270 PRINT AT 11,23;"4"
275 PRINT AT 20,0;"1-4 choose. Hold q to quit."
280 LET s$=""
285 LET done=0
287 LET cap=16
290 GO TO 980
500 LET pr=3
510 LET pc=2
520 LET colour=2
530 LET inkcol=7
540 LET note=0
550 IF p=2 THEN LET pc=18
560 IF p=2 THEN LET colour=1
570 IF p=2 THEN LET note=4
580 IF p=3 THEN LET pr=12
590 IF p=3 THEN LET colour=4
600 IF p=3 THEN LET inkcol=0
610 IF p=3 THEN LET note=7
620 IF p=4 THEN LET pr=12
630 IF p=4 THEN LET pc=18
640 IF p=4 THEN LET colour=6
650 IF p=4 THEN LET inkcol=0
660 IF p=4 THEN LET note=12
670 PAPER colour
680 INK inkcol
690 BRIGHT lit
700 FOR r=pr TO pr+5
710 PRINT AT r,pc;" "
720 NEXT r
770 IF lit=1 THEN PRINT AT pr+2,pc+5;"*"
780 PAPER 0
790 INK 7
800 BRIGHT 0
810 RETURN
900 LET lit=1
910 GO SUB 500
920 BEEP 0.15,note
930 LET lit=0
940 GO SUB 500
950 PAUSE 10
960 RETURN
980 LET s$=s$+STR$ (INT (RND*4)+1)
990 PRINT AT 19,0;"Rounds completed: ";done
1000 PRINT AT 18,0;"WATCH "
1010 FOR i=1 TO LEN s$
1020 IF INKEY$="q" THEN GO TO 1900
1030 LET p=VAL s$(i)
1040 GO SUB 900
1050 NEXT i
1060 IF INKEY$="q" THEN GO TO 1900
1070 PRINT AT 18,0;"Release the keys. "
1080 GO SUB 1600
1090 PRINT AT 18,0;"YOUR TURN "
1100 FOR i=1 TO LEN s$
1110 GO SUB 1500
1120 GO SUB 900
1130 GO SUB 1600
1140 IF k$<>s$(i) THEN GO TO 1800
1150 NEXT i
1160 LET done=done+1
1170 IF done=cap THEN GO TO 1850
1180 GO TO 980
1500 LET k$=INKEY$
1510 IF k$="" THEN GO TO 1500
1520 IF k$="q" THEN GO TO 1900
1530 IF k$<"1" THEN GO TO 1580
1540 IF k$>"4" THEN GO TO 1580
1550 LET p=VAL k$
1560 RETURN
1580 GO SUB 1600
1590 GO TO 1500
1600 LET a$=INKEY$
1610 IF a$="q" THEN GO TO 1900
1620 IF a$<>"" THEN GO TO 1600
1630 RETURN
1800 PRINT AT 18,0;"Different choice. "
1810 BEEP 0.1,-12
1820 PRINT AT 19,0;"Rounds completed: ";done
1830 STOP
1850 PRINT AT 18,0;"Challenge complete. "
1860 PRINT AT 19,0;"Rounds completed: ";done
1870 STOP
1900 PRINT AT 18,0;"Finished. RUN to try again. "
1910 PRINT AT 21,0;" "
1920 STOP
2000 PRINT AT 3,0;"Watch the order of the signals."
2010 PRINT AT 5,0;"Repeat it with keys 1 to 4."
2020 PRINT AT 7,0;"Wait for each cue to finish."
2030 PRINT AT 9,0;"Each round adds one choice."
2040 PRINT AT 11,0;"Complete 16 rounds to finish."
2050 PRINT AT 13,0;"Hold q to quit, even in WATCH."
2060 PRINT AT 15,0;"Release keys, then s to start."
2070 GO SUB 1600
2080 LET k$=INKEY$
2090 IF k$="" THEN GO TO 2080
2100 IF k$="q" THEN GO TO 1900
2110 IF k$<>"s" THEN GO TO 2070
2120 GO SUB 1600
2130 CLS
2140 PRINT "BRIGHT SPARK"
2150 GO TO 100
Replay without returning to the BASIC prompt
The failure and success blocks currently finish with STOP. Replace 1830
and 1870 with jumps to the replay prompt, and add 2200–2270:
1830 GO TO 2200
1870 GO TO 2200
2200 GO SUB 1600
2210 PRINT AT 21,0;"r replay, q quit."
2220 LET k$=INKEY$
2230 IF k$="" THEN GO TO 2220
2240 IF k$="q" THEN GO TO 1900
2250 IF k$<>"r" THEN GO TO 2200
2260 GO SUB 1600
2270 GO TO 2130
Both results now share one decision. The completed count and outcome stay
visible while row 21 offers r replay, q quit.. Reusing this prompt keeps
failure and success equally easy to leave or retry.
The routine drains an old key before showing the prompt. Once it is waiting for a new reading, an empty reading returns directly to 2220. A valid r is released at 2260, then the jump to 2130 clears the old display and rebuilds the board. An unrelated key is released and ignored; q takes the ordinary exit.
Follow the replay path through the source:
| Destination | Work |
|---|---|
| 2130–2150 | Clear the old result, print the title, jump to the board |
| 100–270 | Draw four resting panels and their labels |
| 275 | Restore the controls |
| 280–287 | Empty s$, reset done to 0, set the cap |
| 290, then 980 | Append the first choice of the new game |
| 1000 onward | Present it, then invite the player’s response |
Playback and response each initialise i with their own FOR statement. The
first new input overwrites k$; the renderer selects its defaults on every
call. Fresh state is a consequence of these assignments and entry points,
not of naming a block “restart”.
Why not replay by jumping straight to 980?
Show the explanation
That would append to the old sequence while keeping its completed count. The board might look ready, but the game state would still belong to the previous attempt. Returning through the initialisation resets both what is stored and what is shown.
Play, make a deliberate mistake, and choose r. The next game should begin with one item and 0 completed rounds. Its first item may happen to match the previous one: a fresh random choice does not guarantee a different result.
For a quick success-and-replay check, temporarily set cap=2, finish both
rounds and replay. Restore cap=16 before saving the finished version. If you
keep a different cap, update the instruction at 2040 to match it. Finally
try q at a result. It should show the exit message and return to BASIC with
the intentional STOP report.

Check the whole experience
Give the controls to someone who has not watched you build the game. Let them use the start screen before explaining anything aloud. Observe which messages they notice and when they try their next press. Their questions are evidence about the instructions; their score is not a test they must pass.
Try these specific cases as well:
- Make a wrong first-round choice. The completed count should be 0. Complete three rounds and fail the fourth; it should be 3.
- Hold a number during WATCH. Release it when asked, then make a fresh choice. Hold a valid response key: it should echo once and wait for release.
- Press an unrelated key during YOUR TURN, then a valid choice. The unrelated key should neither fail the round nor advance the response position.
- Hold q during playback, during a response wait and at a result. During a cue, allow its note and repaint to finish. Use one key at a time; do not rely on simultaneous-key chords.
- Turn sound off. The labels, asterisks, status and result must still explain what is happening. Compare the panels without relying on hue: the active marker carries information that colour alone cannot.
There is no input queue during a cue. If someone naturally types the whole
response ahead of the echoed signals, discuss the pace and make the instruction
clearer. Accepting buffered typing would require a different input design;
a longer PAUSE alone would not add a queue.
Refine the signals with a reason
Our note values are 0, 4, 7 and 12. Try changing the third panel’s pitch at 610 from 7 to 9, leaving its visual identity unchanged. Compare how easily you distinguish the four sounds. There is no required melody to imitate: the notes form a vocabulary of choices. Restore 7 or keep a tested alternative.
You can also compare BEEP 0.1,note with the current BEEP 0.15,note at 920.
Does the shorter cue remain easy to recognise? Check identical neighbouring
choices and held-key playback again after a timing change. Shorter is useful
only if people can still separate the events. Restore 0.15 for the supplied
finished version.
Keep the permanent digits outside the repaint areas and retain the asterisk. The original colour associations help orientation; neither brightness nor colour alone should be the only way to identify an active choice. When you alter one thing, check the behaviour it was supporting.
Save a recoverable finished game
Save the finished program with SAVE "spark16", using a different tape name
from the earlier spark checkpoints. Export the recording as a host file,
then reopen it in a fresh session with LOAD "spark16" and RUN.
The tape-saving guide
covers the recording prompt, export and platform-specific controls.
The name inside the tape and the host filename are different things. An export can contain earlier recordings too, so distinct program names help you recover the intended version. A successful SAVE report alone does not prove that you can load the right program again.
You should arrive at the start screen. Play a round, reach a result, replay
and quit. This checks the recovered program’s behaviour, not just its presence.
The .bas listing is readable source; the .tap file contains tape data the
Spectrum loads. Keep both when sharing your work, with a short note naming
the 48K target and the controls.
Complete finished source
10 BORDER 0
20 PAPER 0
30 INK 7
40 CLS
50 PRINT "BRIGHT SPARK"
55 GO TO 2000
100 LET lit=0
110 FOR p=1 TO 4
120 GO SUB 500
130 NEXT p
240 PRINT AT 2,7;"1"
250 PRINT AT 2,23;"2"
260 PRINT AT 11,7;"3"
270 PRINT AT 11,23;"4"
275 PRINT AT 20,0;"1-4 choose. Hold q to quit."
280 LET s$=""
285 LET done=0
287 LET cap=16
290 GO TO 980
500 LET pr=3
510 LET pc=2
520 LET colour=2
530 LET inkcol=7
540 LET note=0
550 IF p=2 THEN LET pc=18
560 IF p=2 THEN LET colour=1
570 IF p=2 THEN LET note=4
580 IF p=3 THEN LET pr=12
590 IF p=3 THEN LET colour=4
600 IF p=3 THEN LET inkcol=0
610 IF p=3 THEN LET note=7
620 IF p=4 THEN LET pr=12
630 IF p=4 THEN LET pc=18
640 IF p=4 THEN LET colour=6
650 IF p=4 THEN LET inkcol=0
660 IF p=4 THEN LET note=12
670 PAPER colour
680 INK inkcol
690 BRIGHT lit
700 FOR r=pr TO pr+5
710 PRINT AT r,pc;" "
720 NEXT r
770 IF lit=1 THEN PRINT AT pr+2,pc+5;"*"
780 PAPER 0
790 INK 7
800 BRIGHT 0
810 RETURN
900 LET lit=1
910 GO SUB 500
920 BEEP 0.15,note
930 LET lit=0
940 GO SUB 500
950 PAUSE 10
960 RETURN
980 LET s$=s$+STR$ (INT (RND*4)+1)
990 PRINT AT 19,0;"Rounds completed: ";done
1000 PRINT AT 18,0;"WATCH "
1010 FOR i=1 TO LEN s$
1020 IF INKEY$="q" THEN GO TO 1900
1030 LET p=VAL s$(i)
1040 GO SUB 900
1050 NEXT i
1060 IF INKEY$="q" THEN GO TO 1900
1070 PRINT AT 18,0;"Release the keys. "
1080 GO SUB 1600
1090 PRINT AT 18,0;"YOUR TURN "
1100 FOR i=1 TO LEN s$
1110 GO SUB 1500
1120 GO SUB 900
1130 GO SUB 1600
1140 IF k$<>s$(i) THEN GO TO 1800
1150 NEXT i
1160 LET done=done+1
1170 IF done=cap THEN GO TO 1850
1180 GO TO 980
1500 LET k$=INKEY$
1510 IF k$="" THEN GO TO 1500
1520 IF k$="q" THEN GO TO 1900
1530 IF k$<"1" THEN GO TO 1580
1540 IF k$>"4" THEN GO TO 1580
1550 LET p=VAL k$
1560 RETURN
1580 GO SUB 1600
1590 GO TO 1500
1600 LET a$=INKEY$
1610 IF a$="q" THEN GO TO 1900
1620 IF a$<>"" THEN GO TO 1600
1630 RETURN
1800 PRINT AT 18,0;"Different choice. "
1810 BEEP 0.1,-12
1820 PRINT AT 19,0;"Rounds completed: ";done
1830 GO TO 2200
1850 PRINT AT 18,0;"Challenge complete. "
1860 PRINT AT 19,0;"Rounds completed: ";done
1870 GO TO 2200
1900 PRINT AT 18,0;"Finished. RUN to try again. "
1910 PRINT AT 21,0;" "
1920 STOP
2000 PRINT AT 3,0;"Watch the order of the signals."
2010 PRINT AT 5,0;"Repeat it with keys 1 to 4."
2020 PRINT AT 7,0;"Wait for each cue to finish."
2030 PRINT AT 9,0;"Each round adds one choice."
2040 PRINT AT 11,0;"Complete 16 rounds to finish."
2050 PRINT AT 13,0;"Hold q to quit, even in WATCH."
2060 PRINT AT 15,0;"Release keys, then s to start."
2070 GO SUB 1600
2080 LET k$=INKEY$
2090 IF k$="" THEN GO TO 2080
2100 IF k$="q" THEN GO TO 1900
2110 IF k$<>"s" THEN GO TO 2070
2120 GO SUB 1600
2130 CLS
2140 PRINT "BRIGHT SPARK"
2150 GO TO 100
2200 GO SUB 1600
2210 PRINT AT 21,0;"r replay, q quit."
2220 LET k$=INKEY$
2230 IF k$="" THEN GO TO 2220
2240 IF k$="q" THEN GO TO 1900
2250 IF k$<>"r" THEN GO TO 2200
2260 GO SUB 1600
2270 GO TO 2130
The supplied game code uses the sample repository’s MIT licence. Include its copyright and permission notice when sharing copies or substantial parts, and credit your own changes. The panels and notes here are created by the program; there is no borrowed artwork pack to account for.
Bright Spark connects one stored order to both presentation and judgement. Its blocking waits suit a game where the world can pause for the player. Volley asks a different question: what changes when the ball keeps moving while we decide?
Sources
Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second
edition (Sinclair Research, 1983), chapter 5 (subroutines and return points),
chapter 18 (keyboard polling), chapter 19 (beeper pitch and duration), and
chapter 20, pp. 141–145 (tape storage, names and SAVE/LOAD).