This program implements a multiplayer word game (Boggle) in three languages—English, German, and Spanish—selectable at runtime via the variable L(R). The game generates a 4×4 grid of letter dice, displays a countdown timer from 9000 units, and accepts words from two players in turn, scoring them by length (4-letter words score 1, up to 10+ letters scoring 39). Custom UDG characters are defined for accented and special letters (Ñ, Ü, Ö, LL, RR, Ch) needed for the Spanish and German modes, with the Spanish Ñ represented internally as CHR$ 157. Multiple rounds are supported, with scores tracked across rounds in arrays X(R) and Y(R).
Program Structure
The program is organised into functional blocks rather than a strict top-down flow. The entry point at line 5 sets round number R=1 and jumps to line 800 (not shown, but expected to handle initialisation and the title/setup sequence). Key functional regions are:
- Lines 5–40: Display routines for the word grid and timer (
GO SUB 20,GO SUB 25). - Lines 50–85: Dice generation — shuffle and assign letter faces using arrays
A(),B(),D$(), andC$(). - Lines 90–165: Main game loop — countdown timer
Tfrom 9000 to 0, keypress detection, and switching between OVER modes for display. - Lines 200–240: Word entry and validation for the active player.
- Lines 250–260: Grid line drawing using
PLOT/DRAW. - Lines 300–325: Player 2 setup after Player 1’s turn ends.
- Lines 330–435: Score reduction input in each language (English 330–355, German 370–395, Spanish 410–435).
- Lines 550–565: Word list swap/restore routine using sentinel value
"QKZ". - Lines 600–739: Scoring, display, and round management.
- Lines 810–855: UDG definition via
POKE USRandREAD/DATA. - Lines 920–2500: Variable initialisation, language string setup, and dimension statements.
UDG Definitions
Eight custom UDGs are defined at line 810 by poking 8-byte bitmaps into USR "x" addresses. These provide special characters needed for multilingual play:
| UDG Char | Purpose |
|---|---|
"N" | Ñ (Spanish) |
"C" | Ç or Ch digraph indicator |
"O" | Ö (German) |
"U" | Ü (German) |
"J" | Horizontal rule / separator glyph |
"H" | Ch digraph symbol |
"R" | RR digraph symbol |
"L" | LL digraph symbol |
In the A$ letter distribution string for Spanish (line 1950), the digraphs Ch, LL, RR are encoded as \h, \l, \r (UDGs H, L, R), and Ñ as \n (UDG N). Line 32 handles display of these multi-character tiles specially, printing “Ch”, “LL”, or “rr” in place of the single UDG code.
Dice Generation Algorithm
The shuffling routine (lines 50–85) uses a probabilistic chain to assign one of 16 dice positions to each of 16 slots without replacement. Array B() tracks which slots have been assigned, and A() accumulates the order. This is not a standard Fisher-Yates shuffle; it relies on repeated random probing and may theoretically loop for long periods if many collisions occur, though in practice convergence is fast for 16 elements.
Each die face is then selected at line 85: D$(I) holds a 6-character face string for die I, and a random face index N is chosen, setting C$(I) to one letter.
Scoring System
Words are scored by length at lines 618 and 654 using a cumulative AND idiom:
- 4 letters → 1 point
- 5 letters → 2 points
- 6 letters → 3 points
- 7 letters → 7 points
- 8 letters → 17 points
- 9 letters → 36 points
- 10 letters → 75 points (cumulative sum)
Words found by both players (joint words) are marked with sentinel "QKZ" in F$() and excluded from scoring. The penalty input (lines 330–435) allows referees to deduct from either player’s score for invalid words.
OVER Technique for Two-Player Hiding
During Player 1’s turn, words are printed with PRINT OVER 1 to XOR them onto the screen, making them invisible against a pre-drawn background. OVER 0 writes normally. The variable O toggles between these modes, and GO SUB 550 toggles the visibility of all entered words so Player 2 cannot see Player 1’s words and vice versa.
Multilingual String Construction
All UI strings are assembled at lines 1960–1990 using the Sinclair BASIC idiom of string multiplication by boolean condition, e.g.:
LET W$=("WORDS" AND L(R)=1)+("PALABRAS" AND L(R)=3)+("Wo"+CHR$ 8+"\oRTER" AND L(R)=2)
Only one condition is true at a time (returns the string), the others return "". CHR$ 8 (cursor left) combined with a UDG is used to simulate an umlaut by overprinting.
Timer and Beep
The countdown runs as a FOR T=9000 TO 0 STEP -1 loop (line 100). At T=1800 (line 105), a one-second beep at pitch -30 warns players of 20% time remaining. The displayed time is INT(T/60), giving an approximate seconds display since each loop iteration is not exactly 1/60th of a second (BASIC overhead makes this an approximation). At timeout, BEEP 2,0 signals end of turn.
Word List and Sentinel Values
Player 1’s words are stored in S$() with lengths in T(). Words also found by Player 2 are marked by overwriting with "QKZ" (lines 235, 305). Player 2’s confirmed unique words go into J$() with lengths in K(). The sentinel "QXZ" is used at line 305 to blank Player 1’s entries before Player 2’s turn. The display routine at line 557 checks for "QKZ" to skip joint words.
Notable Bugs and Anomalies
- The word validation loop at lines 214–216 checks both
S$()andJ$()but usesTO LEN X$slicing without bounds checking, which could cause an error ifLEN X$exceeds the dimension of the string arrays (11 characters forS$, 10 forJ$).
Round and Match Management
The variable R tracks the current round. Scores are stored in X(R) and Y(R). After scoring, line 735 prompts for the next round number; if the entered value matches R, the game loops to line 1100 (language selection for the new round). Otherwise, “END OF MATCH” is printed and execution falls to line 3000 (not shown, likely a final display or halt). Each round can independently select a language, enabling mixed-language matches.
Content
Source Code
5 LET R=1: GO TO 800
15 PRINT OVER O;AT 20,16-(4 AND L(R)=2)-(3 AND L(R)=3);INT (T/60)
20 PRINT OVER 1-O;AT 1,0+(3 AND L(R)=1);K$: PRINT '''
25 LET J=1
27 IF L(R)=3 THEN GO TO 32
30 PRINT OVER 1;" ";: FOR I=J TO J+3: PRINT OVER 1-O;C$(I);"u" AND C$(I)="Q"; OVER 1;(" " AND C$(I)<>"Q"); OVER 1;" ";: NEXT I: PRINT '''
31 GO TO 35
32 PRINT OVER 1;" ";: FOR I=J TO J+3: PRINT OVER 1-O;(C$(I) AND C$(I)<>"\h" AND C$(I)<>"\r" AND C$(I)<>"\l");"u" AND C$(I)="Q";"Ch" AND C$(I)="\h";"LL" AND C$(I)="\l";"rr" AND C$(I)="\r"; OVER 1;(" " AND C$(I)<>"Q" AND C$(I)<>"\h" AND C$(I)<>"\r" AND C$(I)<>"\l"); OVER 1;" ";: NEXT I: PRINT '''
35 LET J=J+4: IF J=17 THEN RETURN
40 GO TO 27
50 LET N=INT (RND*16)+1: LET A(16)=N
55 LET B(N)=INT (RND*16)+1
60 LET N=B(N): IF B(N)<>0 THEN GO TO 55
65 LET A(C)=N: LET C=C+1: IF C=16 THEN GO TO 80
70 GO TO 55
80 FOR I=1 TO 16: LET D$(I)=A$(6*A(I)-5 TO 6*A(I))
85 LET N=INT (RND*6)+1: LET C$(I)=D$(I,N): NEXT I
90 PRINT OVER 1;AT 1,2+(2 AND L(R)=1);P$+I$(1)
95 PRINT OVER 1;AT 20,3;W$: PRINT AT 20,16;T$
96 GO SUB 20
100 FOR T=9000 TO 0 STEP -1
105 IF T=1800 THEN BEEP 1,-30
110 IF INKEY$<>"" THEN GO TO 160
115 NEXT T
120 BEEP 2,0: IF SW=0 THEN GO TO 300
125 GO TO 600
150 LET O=1: GO SUB 550
154 GO SUB 15
155 GO TO 115
160 LET O=0: GO SUB 15
165 GO SUB 550
200 IF L(R)=1 THEN INPUT "ENTER WORD (""0"" TO SEE LETTERS)";X$
201 IF L(R)=3 THEN INPUT "ENTER SU PALABRA, O ""0"" PARA VERLAS LETRAS ";X$
202 IF L(R)=2 THEN INPUT "ENTER WORT (""0"" UM DAS BRETT ZUSEHEN ";X$
204 IF X$="0" THEN GO TO 150
205 IF LEN X$<4 OR LEN X$>10 THEN GO TO 200
210 FOR I=1 TO LEN X$:
211 IF X$(I)=" " THEN GO TO 200
212 IF L(R)=3 AND X$(I)="W" THEN LET X$(I)="\n"
213 NEXT I
214 FOR I=1 TO (S AND S>B)+(B AND B>=S): IF X$=S$(I, TO LEN X$) AND S$(I,LEN X$+1)=" " THEN GO TO 200:
215: IF X$=J$(I, TO LEN X$) AND J$(I,LEN X$+1)=" " THEN GO TO 200:
216 NEXT I
218 LET T(S)=LEN X$: PRINT AT 20,0;S: LET S$(S)=X$
220 PRINT AT S-1-(20 AND S>20)-(20 AND S>40),0+(22 AND S>20)-(11 AND S>40);S$(S, TO T(S))
222 LET S=S+1: IF SW=0 THEN GO TO 200
224 FOR I=1 TO F: IF S$(S-1, TO 10)=F$(I) THEN GO TO 235
225 NEXT I
230 GO TO 200
235 LET K(B)=LEN X$: LET J$(B)=X$: LET S$(S-1)="QKZ": LET F$(I)="QKZ": LET B=B+1
240 GO TO 200
250 FOR I=64 TO 176 STEP 24: PLOT I,143: DRAW 0,-96: NEXT I
255 FOR I=47 TO 143 STEP 24: PLOT 64,I: DRAW 94,0: NEXT I
260 RETURN
300 LET O=0: GO SUB 20
305 FOR I=1 TO S-1: LET F$(I)=S$(I): LET S$(I)="QXZ": LET G(I)=T(I): NEXT I
310 LET F=S-1: LET S=1: LET SW=1
312 PRINT AT 20,0;" "
315 IF L(R)=1 THEN INPUT "PLAYER 2: ENTER INITIALS ";I$(2)
316 IF L(R)=3 THEN INPUT "JUGADOR 2: ENTER INICIALES";I$(2)
317 IF L(R)=2 THEN INPUT "SPIELER 2 ANFANGBUCHSTABEN";I$(2)
319 IF R=1 THEN LET H$=I$(2)
325 GO TO 96
330 IF SW=1 THEN GO TO 345
335 INPUT "REDUCE PLAYER"; BRIGHT 1;" 1 "; BRIGHT 0;"SCORE BY ? (99 TO SEE BOARD AND/OR UNSCROLL ";A1
340 IF A1=99 THEN GO TO 740
345 LET SW=1: INPUT "REDUCE PLAYER"; BRIGHT 1;" 2 "; BRIGHT 0;"SCORE BY ? (99 TO SEE BOARD AND/OR UNSCROLL ";A2
350 IF A2=99 THEN GO TO 740
355 RETURN
370 IF SW=1 THEN GO TO 385
375 INPUT OVER 1;"ZIEHEN ? AUS SPIELER"; BRIGHT 1;" 1 "; BRIGHT 0;"AB (99 ZUM BRETT U/O ZURu";CHR$ 8;"\oCKROLLEN) ";A1
380 IF A1=99 THEN GO TO 740
385 LET SW=1: INPUT OVER 1;"ZIEHEN ? AUS SPIELER"; BRIGHT 1;" 2 "; BRIGHT 0;"AB (99 ZUM BRETT U/O ZURu";CHR$ 8;"\oCKROLLEN) ";A2
390 IF A2=99 THEN GO TO 740
395 RETURN
410 IF SW=1 THEN GO TO 425
415 INPUT OVER 1;"QUITAR \c \a\l JUGADOR"; BRIGHT 1;" 1 "; BRIGHT 0;"? (99 PARAEL TABLERO Y/O ARROLLAR ATRA";CHR$ 8;"\u\s) " ;A1
420 IF A1=99 THEN GO TO 740
425 LET SW=1: INPUT OVER 1;"QUITAR \c \a\l JUGADOR"; BRIGHT 1;" 2 "; BRIGHT 0;"? (99 PARAEL TABLERO Y/O ARROLLAR ATRA";CHR$ 8;"\u\s) " ;A2
430 IF A2=99 THEN GO TO 740
435 RETURN
550 LET BB=1:: FOR I=1 TO S-1
552 IF S$(I, TO 3)="QKZ" THEN LET S$(I)=J$(BB)
557 PRINT OVER O;AT I-1-(20 AND I>20)-(20 AND I>40),0+(22 AND I>20)-(11 AND I>40);S$(I, TO T(I))
558 IF S$(I, TO 10)=J$(BB) THEN LET S$(I)="QKZ"
559 IF S$(I, TO 3)="QKZ" THEN LET BB=BB+1
560 NEXT I
562 GO SUB 250
565 RETURN
600 LET SW=0
601 CLS : LET J=1
602 FOR I=J TO J+3: PRINT AT (J-1)/4,28+I-J;C$(I);: NEXT I: PRINT AT (J-1)/4,27;"▌": LET J=J+4: IF J=17 THEN GO TO 604
603 GO TO 602
604: PRINT OVER 1;AT 0,0;(B$+W$ AND L(R)<>3)+(W$+B$ AND L(R)=3)+": ";
605 LET SCR1=0: FOR I=1 TO B-1: PRINT J$(I, TO K(I));" ";: IF PEEK 23688<K(I+1)+7 AND PEEK 23689>19 THEN PRINT
606 NEXT I
607 PRINT : PRINT : PRINT TAB 12;I$(1): IF B<4 THEN PRINT
609 FOR I=1 TO F
615 IF F$(I, TO 3)="QKZ" THEN GO TO 632
618 LET X=1+(1 AND G(I)=5)+(2 AND G(I)=6)+(4 AND G(I)=7)+(10 AND G(I)=8)+(19 AND G(I)=9)+(39 AND G(I)=10)
628 LET SCR1=SCR1+X
630 PRINT F$(I);X,
632 NEXT I
636 PRINT TAB 26;"\j": PRINT TAB 26;SCR1
637 PRINT : PRINT : PRINT TAB 12;I$(2): IF B<4 THEN PRINT
638 LET SCR2=0
639 FOR I=1 TO S-1
640 IF S$(I, TO 3)="QKZ" THEN GO TO 665
654 LET Y=1+(1 AND T(I)=5)+(2 AND T(I)=6)+(4 AND T(I)=7)+(10 AND T(I)=8)+(19 AND T(I)=9)+(39 AND T(I)=10)
657 LET SCR2=SCR2+Y
660 PRINT S$(I, TO 10);Y,
665 NEXT I
670 PRINT TAB 26;"\j": PRINT TAB 26;SCR2
672 IF PEEK 23689<4 THEN PRINT '
675 GO SUB 290+40*L(R)
720 LET SCR1=SCR1-A1: LET SCR2=SCR2-A2
725 CLS : PRINT TAB 13;G$;TAB 23;H$
726 IF I$(1)=G$ THEN GO TO 729
727 LET Z=SCR1: LET SCR1=SCR2: LET SCR2=Z
729 LET X(R)=SCR1: LET Y(R)=SCR2: LET Z$="EGSEDSIAE"
730 FOR I=1 TO R: PRINT AT I+1,0;R$(LEN R$-5 TO LEN R$-1);" ";I;"(";Z$(3*L(R)+L(I)-3);") ";X(I);: PRINT AT I+1,23;Y(I): NEXT I
735 PRINT OVER 1;AT 21,0;R$: INPUT RR
736 PRINT OVER 1;AT 21,0;R$
737 LET R=R+1: IF RR=R THEN GO TO 1100
739 PRINT "END OF MATCH": GO TO 3000
740 CLS : PRINT '''': GO SUB 25
745 IF INKEY$<>"" THEN GO TO 601
746 GO TO 745
810 FOR I=1 TO 8: READ V$: FOR J=0 TO 7: READ Y: POKE USR V$+J,Y: NEXT J: NEXT I
815 DATA "N",60,66,98,82,74,70,66,0
820 DATA "C",16,0,16,48,64,68,68,56
825 DATA "O",36,36,0,0,0,0,0,0
830 DATA "U",2,4,8,0,0,0,0,0
835 DATA "J",0,255,0,0,0,0,0,0
840 DATA "H",4,20,100,134,133,69,53,0
842 DATA "R",0,119,204,136,136,136,136,0
845 DATA "L",0,132,132,132,132,132,231,0
850 DATA 16,-1,0,15,1,1,12,-1,1,7,1,1,4,0,-1,8,-1,1,3,-1,-1
855 DATA 6,0,1,2,-1,0,1,0,-1,5,0,-1,9,1,-1,14,-1,0,13,0,0
920 DIM R(20): DIM L(20): DIM X(20): DIM Y(20)
925 DIM I$(2,3)
1000 LET O=0: LET C$="NURLDOGEOGOGENOB": GO SUB 250
1005 PRINT ''''': GO SUB 25
1010 PAUSE 120: LET A=148: LET B=60: PRINT BRIGHT 1;AT 14,18;"B": FOR I=1 TO 14: READ X: READ Y: READ Z
1015 REM NEXT I: GO TO 1050
1020 FOR J=1 TO 24: LET A=A+Y: LET B=B+Z: PLOT A,B: NEXT J: PLOT BRIGHT 1;A,B: PLOT PAPER 0;148,60
1025 FOR J=0 TO 4: PLOT 140-16*J,39-8*J: DRAW 10,0: NEXT J
1030 FOR J=0 TO 5: PRINT AT 16+J,18-2*J;C$(X)
1035 PAUSE 10: PRINT OVER 1;AT 16+J,18-2*J;C$(X): NEXT J
1040 PRINT AT 21,I+1+(8 AND I>6)+(1 AND I>11);C$(X)
1045 PLOT PAPER 0;A,B: NEXT I
1100 PAUSE 120: CLS : PRINT ''': PRINT TAB 10;"1 ENGLISH"''TAB 10;"2 DEUTSCH"''TAB 10;"3 ESPA\nOL"
1110 INPUT L(R): IF L(R)<>1 AND L(R)<>2 AND L(R)<>3 THEN GO TO 1110
1150 DIM A(16): DIM B(16): DIM F(60): DIM G(60): DIM S(60): DIM T(60): DIM J(50): DIM K(50)
1160 DIM S$(60,11): DIM F$(60,10): DIM J$(50,10): DIM D$(16,6): DIM C$(16,1)
1940 IF L(R)=1 THEN LET A$="BTLAYISHrOmACASLErCDPAmEvGTINEGUYKELOQABmJTLSEPUGLrUwIEHYEFIUTODKNOrIXFBDANvEZACIATOINEHPSNwDOSE"
1945 IF L(R)=2 THEN LET A$="BTLANIEHrOMACASLErCOPAmEvGTINEGUrKELOQABmJTLSEPUGLrUwIEHYEFIUTODKNOrIXFBDANVEZACIATOINEHPSNwDOSE"
1950 IF L(R)=3 THEN LET A$="BTLAYISHrOmACASLOrCDPAmOvGTINEGUA\hELOQABmJTLSEPUGLrU\nIEH\rEFIUTOD\hNOrIXFBDANvEZACIATOINEHPSN\lDOSE"
1960 LET W$=("WORDS" AND L(R)=1)+("PALABRAS" AND L(R)=3)+("Wo"+CHR$ 8+"\oRTER" AND L(R)=2)
1965 LET T$=(" SECONDS LEFT" AND L(R)=1)+(" SEGUNDOS QUEDAN" AND L(R)=3)+("SEKUNDEN BLEIBEN" AND L(R)=2)
1970 LET K$=(" TOUCH ANY KEY TO WRITE" AND L(R)=1)+(" CUALQUIER TECLA PARA ESCRIBIR" AND L(R)=3)+("IRGENDEINE TASTE UM ZU SCHREIBEN" AND L(R)=2)
1975 LET P$=("ONE MOMENT PLEASE, " AND L(R)=1)+("EIN AUGENBLICK BITTE, " AND L(R)=2)+("UN MOMENTO POR FAVOR, " AND L(R)=3)
1980 LET B$=("JOINT " AND L(R)=1)+("GEMEINSAME " AND L(R)=2)+(" EN COMu"+CHR$ 8+"\uN" AND L(R)=3)
1990 LET R$=("NUMBER OF NEXT ROUND?" AND L(R)=1)+("NUMMER DER NA"+CHR$ 8+"\oCHSTE RUNDE?" AND L(R)=2)+("\cNu"+CHR$ 8+"\uMERO DE LA PRo"+CHR$ 8+"\uXIMA TANDA?" AND L(R)=3)
2400 LET F=1: LET S=1: LET B=1: LET SW=0: LET C=1: LET O=0:
2425 IF L(R)=1 THEN INPUT "PLAYER 1: ENTER INITIALS ";I$(1)
2430 IF L(R)=3 THEN INPUT "JUGADOR 1 ENTER INICIALES ";I$(1)
2435 IF L(R)=2 THEN INPUT "SPIELER 1 ANFANGBUCHSTABEN";I$(1)
2450 CLS : GO SUB 250
2455 IF R=1 THEN LET G$=I$(1)
2460 PRINT AT 1,2+(2 AND L(R)=1);P$;I$(1)
2475 GO TO 50
2500 REM "BOGGLE 3"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

