Simon Says is a memory sequence game in which the computer generates a growing random sequence of digits (0–7), displays each step using a color-coded block graphic character (CHR$ 143), and then requires the player to reproduce the sequence via keyboard input. Each step in the sequence is shown with INK set to the digit’s value (0–7), producing eight distinct colors for visual feedback, while BEEP generates a matching tone scaled by position. The display subroutine at line 1000 uses a compact layout trick: `AT 6, x*3+30*(x=0)` shifts the cursor right across the screen for digits 1–7 but adds 30 columns when x=0 to wrap it to a visible position, compensating for INK 0 being invisible against the background. A BRIGHT 1 block graphic (CHR$ 143, a solid filled square) is printed then erased with CHR$ 8 and CHR$ 32 to flash the cue briefly. The score accumulates as the sequence length grows, and on an error the full sequence is replayed at a fixed pace before the score is shown.
Program Structure
The program is organized into four logical sections:
- Initialization (lines 5–15): Sets screen attributes, dimensions a 32-character blank string
b$used for clearing the status line, and resets the sequence stringr$. - Sequence generation and display (lines 20–50): Appends one random digit (0–7) to
r$, then plays back the entire growing sequence through the display subroutine. - Player input and validation (lines 100–155): Reads keypresses, rejects anything outside
"0"–"7", shows each cue as it is entered, and checks against the stored sequence. On success, prints the running total and loops back to extend the sequence. - Error handler (lines 500–530): Displays a flashing error message, replays the full sequence at a fixed tempo, shows the score, waits for
R, then restarts withRUN.
Display Subroutine (lines 1000–1010)
The subroutine at line 1000 is the heart of the game’s audio-visual feedback. It is called with x set to the digit value (0–7) and t set to the note duration.
PRINT AT 6, x*3+30*(x=0)— positions the cursor. For digits 1–7, the column isx*3(3, 6, …, 21). For x=0, the expression30*(x=0)evaluates to 30, placing the cue far to the right to keep INK 0 (black) visible against the yellow (PAPER 6) background rather than at column 0 where it might be confused with absence.INK x; BRIGHT 1; CHR$ 143— prints a solid block graphic in the color corresponding to the digit, with brightness on for vividness.BEEP t, x*7+56*(x=0)— sounds a note. For digits 1–7 the pitch isx*7semitones above middle C; for x=0 the offset of 56 produces a high note so it is audibly distinct despite sharing INK 0 treatment.CHR$ 8; CHR$ 32— backspaces and prints a space to erase the block after the beep, creating a brief flash effect without any PAUSE.
Sequence Storage
The sequence is stored as a string r$ of digit characters rather than a numeric array. Each new digit is appended with r$=r$+STR$ x (line 25), and individual values are recovered with VAL r$(j) (lines 40, 510). This approach is memory-efficient but limits sequence length to the maximum string length (at line 5, DIM b$(32) is a blank-padding string, not the sequence store). In practice the game will end by human error long before string length becomes an issue.
Tempo Scaling
The display duration t is computed at line 1000 as 1/n, where n is the current sequence length. This means cues play faster as the sequence grows, increasing difficulty organically. During the error replay at line 510, t is fixed at 0.8 seconds per cue so the player can observe the correct sequence at a comfortable pace.
Input Debouncing
Line 130 uses IF INKEY$=i$ THEN GO TO 130 to spin-wait until the key is released before proceeding to the comparison at line 135. This prevents a single keypress from registering multiple times across loop iterations — a standard INKEY$ debounce idiom.
Screen Clearing Trick
b$ is dimensioned at line 5 as a 32-character string, which is initialized to spaces by DIM. It is used at lines 145 and 515 as PRINT AT 20,0;b$; AT 20,0;… to overwrite the full status line with spaces before printing the new message, avoiding CLS and the resulting screen flash.
Anomalies and Notes
INK 9at line 5 and line 500 is not a standard Spectrum INK value (valid range 0–9, where 9 means “transparent/contrast”). Its effect in the PAPER 6 context at line 500 combined withFLASH 1produces a high-contrast error display, but INK 9 behavior can be platform-dependent.- The delay loops at lines 150 and 505 (
FOR j=1 TO 100/250: NEXT j) are timing delays whose actual duration depends on processor speed and will behave differently on accelerated hardware. RANDOMIZEat line 10 without an argument seeds from the system clock each time the sequence grows, which is called every round viaGO TO 20. SinceRANDOMIZEis only executed once per round extension and RND is called immediately after, this is effectively a fresh seed each round.- Line 530 uses
RUNrather thanGO TO 5, which re-executes initialization includingDIM b$(32)and resets all variables cleanly between games.
Content
Source Code
5 BORDER 7:PAPER 6:INK 9:BRIGHT 0:CLS :DIM b$(32)
10 RANDOMIZE
15 LET r$=""
20 LET x= INT \{19}\{0}(RND*8)
25 LET r$=r$+ STR$ x
30 LET n= LEN r$
35 FOR j=1 TO n
40 LET x= VAL r$(j)
45 GO SUB 1000
50 NEXT j
100 PRINT AT 20,0;"NOW YOU REPEAT THE SEQUENCE"
105 FOR j=1 TO n
110 LET i$= INKEY$
115 IF i$<"0" OR i$>"7" THEN GO TO 110
120 LET x= VAL i$
125 GO SUB 1000
130 IF INKEY$=i$ THEN GO TO 130
135 IF i$ <>r$(j) THEN GO TO 500
140 NEXT j
145 PRINT AT 20,0;b$; AT 20,0;"Total so far: ";n
150 FOR j=1 TO 100:NEXT j
155 CLS :GO TO 20
500 PRINT AT 20,0; INK 9; FLASH 1;"ERROR!!!!! The sequence was"
505 FOR j=1 TO 250:NEXT j
510 LET t=.8:FOR j=1 TO n:LET x= VAL r$(j):GO SUB 1005:NEXT j
515 PRINT AT 20,0;b$; AT 20,0;"You scored ";n-1'"Press ""R"" to try again"
520 IF INKEY$ <>"r" THEN GO TO 520
530 RUN
1000 LET t=1/n
1005 PRINT AT 6,x*3+30*(x=0); INK x; BRIGHT 1; CHR$ 143;:BEEP t,x*7+56*(x=0):PRINT CHR$ 8; CHR$ 32
1010 RETURN
9000 SAVE "SIMON SAYS" LINE 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
