A game that always chooses BOTTLE soon runs out of mystery. Move the content into DATA and choose among twenty-four familiar words. The finished program also adds a title screen explaining the controls and free repeat guesses.
Add lines 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 220, 230, 240, 9000, 9010, 9020, 9030.
Replace lines 200, 210, 780.
20 RANDOMIZE
30 PRINT AT 3,10; INK 5; BRIGHT 1;"C I P H E R"
40 PRINT AT 7,3;"Find the hidden word."
50 PRINT AT 9,2;"Reveal every matching letter."
60 PRINT AT 11,3;"Seven mistakes per word."
70 PRINT AT 13,3;"Repeat guesses cost nothing."
80 PRINT AT 17,3;"S starts. Q quits."
90 GO SUB 8000
100 IF k$="q" THEN STOP
110 IF k$<>"s" THEN GO TO 90
200 LET wins=0: LET losses=0: LET round=0: LET last=0: LET total=24
210 LET pick=INT (RND*total)+1
220 IF pick=last THEN GO TO 210
230 LET last=pick: LET round=round+1: RESTORE 9000
240 FOR i=1 TO pick: READ w$: NEXT i
780 IF k$=" " THEN GO TO 210
9000 DATA "WINDOW","BOTTLE","KETTLE","LADDER","RABBIT","GARDEN"
9010 DATA "POCKET","CANDLE","PILLOW","BUTTON","BASKET","BRIDGE"
9020 DATA "ORANGE","SILVER","HAMMER","ROCKET","JACKET","FOREST"
9030 DATA "CAMERA","MARKET","CARPET","SHELL","TUNNEL","STREAM"Complete source at this checkpoint
10 BORDER 0: PAPER 0: INK 7: BRIGHT 0: CLS
20 RANDOMIZE
30 PRINT AT 3,10; INK 5; BRIGHT 1;"C I P H E R"
40 PRINT AT 7,3;"Find the hidden word."
50 PRINT AT 9,2;"Reveal every matching letter."
60 PRINT AT 11,3;"Seven mistakes per word."
70 PRINT AT 13,3;"Repeat guesses cost nothing."
80 PRINT AT 17,3;"S starts. Q quits."
90 GO SUB 8000
100 IF k$="q" THEN STOP
110 IF k$<>"s" THEN GO TO 90
200 LET wins=0: LET losses=0: LET round=0: LET last=0: LET total=24
210 LET pick=INT (RND*total)+1
220 IF pick=last THEN GO TO 210
230 LET last=pick: LET round=round+1: RESTORE 9000
240 FOR i=1 TO pick: READ w$: NEXT i
250 LET d$="": LET t$="": LET m$="": LET left=7: LET u$="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
260 FOR i=1 TO LEN w$: LET d$=d$+"_": NEXT i
270 LET a$="Choose a letter.": GO SUB 2000
300 GO SUB 2500
310 GO SUB 8000
320 IF CODE k$=13 THEN GO TO 600
330 LET c=CODE k$
340 IF c<97 OR c>122 THEN GO TO 310
350 LET g$=CHR$ (c-32): LET seen=0
355 IF t$="" THEN GO TO 390
360 FOR i=1 TO LEN t$: IF t$(i)=g$ THEN LET seen=1
370 NEXT i
380 IF seen=1 THEN LET a$=g$+" already tried. No cost.": GO TO 300
390 LET t$=t$+g$: LET found=0: LET u$(c-96 TO c-96)="."
395 PRINT AT 14+INT ((c-97)/13),3+2*((c-97)-13*INT ((c-97)/13));"."
400 FOR i=1 TO LEN w$
410 IF w$(i)=g$ THEN LET d$(i TO i)=g$: LET found=found+1
420 NEXT i
430 IF found>0 THEN LET a$=g$+" reveals "+STR$ found+" letter(s)."
440 IF found=0 THEN LET left=left-1: LET m$=m$+g$: LET a$=g$+" is not in the word."
450 IF d$=w$ THEN LET wins=wins+1: LET a$="Word found!": GO TO 700
460 IF left=0 THEN LET losses=losses+1: LET a$="No guesses left. Word revealed.": GO TO 700
470 GO TO 300
600 CLS : PRINT AT 3,10; INK 5; BRIGHT 1;"C I P H E R"
610 PRINT AT 7,3;"PAUSED - word stays hidden."
620 PRINT AT 10,3;"C continues this word."
630 PRINT AT 12,3;"R resets words and scores."
640 PRINT AT 14,3;"Q quits to BASIC."
650 GO SUB 8000
660 IF k$="q" THEN STOP
670 IF k$="r" THEN GO TO 200
680 IF k$="c" THEN GO SUB 2000: GO TO 300
690 GO TO 650
700 GO SUB 2000
710 PRINT AT 6,16-LEN w$; INK 4; BRIGHT 1;
720 FOR i=1 TO LEN w$: PRINT w$(i);" ";: NEXT i
730 IF left=0 THEN PRINT AT 6,16-LEN w$; INK 6; BRIGHT 1;: FOR i=1 TO LEN w$: PRINT w$(i);" ";: NEXT i
740 PRINT AT 21,1;"SPACE next. R resets. Q quits. "
750 GO SUB 8000
760 IF k$="q" THEN STOP
770 IF k$="r" THEN GO TO 200
780 IF k$=" " THEN GO TO 210
790 GO TO 750
2000 CLS
2010 PRINT AT 1,2; INK 5; BRIGHT 1;"CIPHER";AT 1,19;"WORD ";round
2020 PRINT AT 3,2;"Won ";wins;" Lost ";losses
2110 PRINT AT 12,2; INK 5;"UNTRIED LETTERS"
2120 FOR j=1 TO 26
2160 PRINT AT 14+INT ((j-1)/13),3+2*((j-1)-13*INT ((j-1)/13)); INK 7;
2170 PRINT u$(j);
2190 NEXT j
2200 PRINT AT 21,1;"Letter guesses. ENTER pauses."
2205 GO SUB 2500
2210 RETURN
2500 PRINT AT 6,16-LEN d$; INK 7; BRIGHT 1;
2510 FOR i=1 TO LEN d$: PRINT d$(i);" ";: NEXT i
2520 PRINT AT 9,2; INK 6;"MISTAKES LEFT: ";left
2530 PRINT AT 10,2; INK 6;
2540 FOR i=1 TO 7
2550 IF i<=left THEN PRINT "O ";
2560 IF i>left THEN PRINT ". ";
2570 NEXT i
2580 PRINT AT 17,2;"Misses: ";m$
2590 LET b$=a$+" ": PRINT AT 19,1; INK 6;b$( TO 30)
2600 RETURN
8000 LET k$=INKEY$
8010 IF INKEY$<>"" THEN GO TO 8010
8020 LET k$=INKEY$: IF k$="" THEN GO TO 8020
8030 IF CODE k$>=65 AND CODE k$<=90 THEN LET k$=CHR$ (CODE k$+32)
8040 RETURN
9000 DATA "WINDOW","BOTTLE","KETTLE","LADDER","RABBIT","GARDEN"
9010 DATA "POCKET","CANDLE","PILLOW","BUTTON","BASKET","BRIDGE"
9020 DATA "ORANGE","SILVER","HAMMER","ROCKET","JACKET","FOREST"
9030 DATA "CAMERA","MARKET","CARPET","SHELL","TUNNEL","STREAM"RUN now opens the title. S starts a fresh session and Q quits. Complete or lose a word, then press Space: the score stays, the histories clear and the next word differs from the one just played. R starts a new session; it may choose any word.
Choose a place in the list
DATA holds the words at 9000–9030. The statements do not display them or immediately assign them to w$. READ consumes the next item from that list. RESTORE 9000 returns the reading position to the first DATA statement at or after 9000.
RND supplies a value from zero up to, but not including, one. Multiplying by total gives a value below twenty-four. INT drops the fractional part; adding one chooses an index from one to twenty-four. RANDOMIZE near the start seeds the generator from the machine’s timing.
The counted READ loop visits items from the beginning through pick, replacing w$ each time. After the loop, w$ holds the selected word. RESTORE is essential: without it, repeated rounds would carry on reading from the previous location and eventually run past the list.
The value last remembers the previous index. If a new selection equals it, choose again. That prevents an immediate repeat during a session; it does not promise that every word appears before one returns. The reset sets last to zero, which is outside the valid index range.
If pick is 3, which word reaches w$, and why does the next round need RESTORE?
Show the explanation
KETTLE. The three READs take WINDOW, BOTTLE and KETTLE. Reading has moved past those items; RESTORE returns the next selection to the same starting point, so its index still refers to the intended word.
Content changes the decisions
A familiar word can still be awkward when few useful letters have been revealed. Repeated letters may reward one guess several times. Word length alone does not settle difficulty: familiarity, likely alternatives and letter distribution also matter.
The current list uses uppercase words of four to eight letters. Keep at least two distinct entries if you change it, because rejecting the previous selection cannot finish with a one-item list. Keep total equal to the number of DATA entries. Too small a total leaves the tail unreachable; too large can make READ run out of data. Stay within the stated word length while using this board layout.
The title’s GO SUB uses the same release gate as the game. Its controls belong to its own loop, so S starts there but is an ordinary guess during a round. The program remains deliberately silent, and every input waits for a separate press.
Play a win, a loss and another word. Pause halfway through, resume, reset and quit. A successful round should preserve the score on Space while rebuilding the allowance, revealed string and alphabet for the new answer.
Sources
Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapter 6, chapter 11, chapter 18.
Run it here
This unit's program, built for you.
- Program
- cipher.tap
- Machine
- ZX Spectrum 48K (PAL)