Play the stored order
Read each stored choice, turn its digit into a panel number and play the sequence with a way to quit.
We can read the order on screen. Now let the Spectrum read it and present the signals. The string will supply the choices; the cue routine already knows how to show and sound each one.
Continue from Remember an order, loading your saved spark if
needed. Keep its board, renderer at 500 and cue routine at 900. This lesson
changes the caller: instead of always supplying panels 1–4, it will visit the
characters of s$ in order.
Keyboard notes for this lesson
In extended mode, J gives VAL and N gives INKEY$.
GO TO is G after a line number.
Visit positions, then choose panels
Delete 285, removing the extra appended choice. Replace 290, 300, 310 and 320, and add 315:
290 PRINT AT 18,0;"WATCH"
300 FOR i=1 TO LEN s$
310 LET p=VAL s$(i)
315 GO SUB 900
320 NEXT i
Line 280 still sets s$="314". The new line 290 replaces the diagnostic order
with WATCH. Since RUN clears the screen at line 40, the old length and
first/last diagnostics disappear too.
FOR i=1 TO LEN s$ visits every position in the string. i means which item
we are visiting. For this order it takes the values 1, 2 and 3.
The cue needs a numeric p, while s$(i) supplies a one-character string.
VAL s$(i) evaluates that text as a numeric expression. For our stored digits,
VAL "3" produces the number 3.
VAL can evaluate more than a single digit. It is not a test that arbitrary
text is a safe panel choice. Here we wrote the string ourselves and know that
every character is one of "1"–"4". Player input will need checking before
conversion.
i |
s$(i) |
Numeric p |
Cue |
|---|---|---|---|
| 1 | "3" |
3 | Lower-left panel |
| 2 | "1" |
1 | Upper-left panel |
| 3 | "4" |
4 | Lower-right panel |
GO SUB 900 plays that panel’s cue and returns to NEXT i. The next loop visit
reads another character. When all three have been visited, execution reaches
STOP at 330.
Run it. Expect 3, 1, 4, with every panel returning to rest. The printed order has gone: the signals now carry the information the player must remember.
Why not use p as the loop counter again?
Show the explanation
The old demonstration used panel numbers in counting order, so FOR p=1 TO 4
was useful. Now the position and panel number can differ. At position 1 the
panel is 3. Keeping i and p separate lets the sequence contain any order,
including repeated choices.
The renderer still uses r to fill its rows. Changing i inside that routine
would disturb the caller’s traversal. The cue changes drawing values and
lit; it leaves i and s$ alone.
Complete fixed playback program
10 BORDER 0
20 PAPER 0
30 INK 7
40 CLS
50 PRINT "BRIGHT SPARK"
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"
280 LET s$="314"
290 PRINT AT 18,0;"WATCH"
300 FOR i=1 TO LEN s$
310 LET p=VAL s$(i)
315 GO SUB 900
320 NEXT i
330 STOP
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
Make two identical choices distinguishable
Replace the quoted text on line 280 with "22" and run again. We should
see two activations of panel 2, with its asterisk disappearing between
them. Two different locations would reveal the change of choice even with
poor pacing; two identical locations reveal whether the event has an end.
The cue routine already supplies that end. Lines 930–940 repaint the panel at
rest, and line 950 requests an extra ten frames of silence. We keep that
resting interval instead of adding another delay in the caller. At 50 Hz,
ten frames are a fifth of a second; a held or newly pressed key can shorten
PAUSE, and BASIC drawing takes time as well.
Try the same order while holding a number key. The extra pause may shorten, but each note still finishes and the renderer still removes the marker before the next cue. This is the pacing choice we made in lesson 2. It is not a promise that every cue takes an identical amount of time.
Listen as well as watch when sound is available. The notes for "22" have the
same pitch, but should be separate events. With sound off, the two appearances
of the asterisk must still make sense. If they merge into one long highlight,
check that lines 930–950 remain in the cue routine.
Try "1234" to check every position and note association, then restore line
280 to s$="314". We are choosing predictable test data before introducing
chance.
Let the player leave during playback
A three-item demonstration ends quickly. Later orders will be longer, so add an ordinary quit route now. Add 295, 305, 325 and 1900–1920:
295 PRINT AT 20,0;"Hold q to quit."
305 IF INKEY$="q" THEN GO TO 1900
325 IF INKEY$="q" THEN GO TO 1900
1900 PRINT AT 18,0;"Finished. RUN to try again. "
1910 PRINT AT 21,0;" "
1920 STOP
INKEY$ reads the keyboard and gives text: a recognised character, or the empty
string "" when no character is returned. We compare that reading with lower-case "q". This direct test
uses one reading; it does not read again to decide what the key was.
GO TO transfers
execution to the named line without saving a return point. That suits quitting:
we do not want to return to the loop afterwards. GO SUB saves a return point
because a routine is expected to finish and hand control back.
Line 305 checks before every cue. Line 325 checks after the final cue too.
Hold q until the program finishes. BASIC cannot check it while executing
BEEP or the renderer. A short tap entirely inside a cue can be missed; a
held q is seen at the next check. The extra pause can also shorten while q is
held, but the note and repaint still finish.
The quit block prints a clear message, clears the reserved bottom status row and stops. Trailing spaces erase longer text already on that row. They do not change the panel labels, which have their own rows.
Run once without pressing a key, then run again and hold q during a cue.
Expect Finished. RUN to try again. and the intentional STOP report. The
active panel should have returned to rest before the quit message appears.
Would checking only at line 305 catch q held during the last cue?
Show the explanation
No. After that cue, NEXT i finishes the loop and execution no longer visits
305. Line 325 covers this boundary. A check that works between items can still
miss the transition out of the whole sequence.
Complete program to keep
10 BORDER 0
20 PAPER 0
30 INK 7
40 CLS
50 PRINT "BRIGHT SPARK"
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"
280 LET s$="314"
290 PRINT AT 18,0;"WATCH"
295 PRINT AT 20,0;"Hold q to quit."
300 FOR i=1 TO LEN s$
305 IF INKEY$="q" THEN GO TO 1900
310 LET p=VAL s$(i)
315 GO SUB 900
320 NEXT i
325 IF INKEY$="q" THEN GO TO 1900
330 STOP
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
1900 PRINT AT 18,0;"Finished. RUN to try again. "
1910 PRINT AT 21,0;" "
1920 STOP
Save this version as spark. We can now present a stored order and leave
playback cleanly. Next we’ll give the player a turn and compare their choices
with that same string.
Sources
Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second
edition (Sinclair Research, 1983), chapters 4–5 (loops and subroutines), chapter
8, p. 51 (string positions), chapter 9 (VAL), and chapter 18, pp. 129–131
(PAUSE and INKEY$).