--- title: "WORDSQUARE" id: 54555 type: "computer_media" slug: "wordsquare" url: "http://localhost/computer_media/wordsquare/" markdown_url: "http://localhost/computer_media/wordsquare.md" published_at: "2024-06-02T16:56:03+00:00" modified_at: "2026-03-30T21:46:28+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/06/wordsquare-2.png" excerpt: "Build and solve your own word search puzzles with this BASIC program that places words in eight directions across a 20×20 letter grid." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "James DuPuy" slug: "james-dupuy" taxonomy: "indiv" url: "http://localhost/indiv/james-dupuy/" - name: "Tim Hartnell" slug: "tim-hartnell" taxonomy: "indiv" url: "http://localhost/indiv/tim-hartnell/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 51207 title: "CATS Library Tape 6" type: "computer_media" url: "http://localhost/computer_media/cats-library-tape-6/" media_type: "Program" programmers: - name: "Tim Hartnell" slug: "tim-hartnell" taxonomy: "indiv" url: "http://localhost/indiv/tim-hartnell/" - name: "James DuPuy" slug: "james-dupuy" taxonomy: "indiv" url: "http://localhost/indiv/james-dupuy/" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/06/wordsquare-2.png" - url: "http://localhost/wp-content/uploads/2024/06/wordsquare-1.png" media_type_tags: "Game" --- This program generates word search puzzles by placing a user-specified list of 2 to 20 words randomly onto a 20×20 grid, with each word placed in one of eight directional orientations (horizontal, vertical, and diagonal, both forward and backward). After placement, empty grid cells are filled with random uppercase letters using CHR$(INT(RND*26)+65). The program supports an optional display-suppression mode (pressing N at the start hides words as they are placed), and offers printer output via LPRINT for both the word list and the completed grid. POKEs to addresses 23609 and 23658 adjust the keyboard repeat rate and the CAPS LOCK flag respectively. The title screen uses a BEEP-driven animation loop that prints “WORDSQUARE” repeatedly while playing a rising tone sequence. Translated from TS1000 to TS2068 by James Dupuy. *** ## Program Analysis ### Program Structure The program is organized into several distinct phases: 1. **Title/intro sequence** (lines 2–7): Animated BEEP loop printing “WORDSQUARE”, then screen setup with BRIGHT and BORDER. 2. **User input phase** (lines 10–190): Collects the word count and each word, storing them in the 2D string array `C$`. 3. **Word placement loop** (lines 200–550): Iterates over each word, randomly choosing a start position and direction, checking for conflicts, then writing placed letters into the grid array `H$`. 4. **Grid fill and display** (lines 560–656): Fills empty cells with random letters, draws a border, and optionally triggers a COPY. 5. **Answer reveal** (lines 660–795): Optionally prints the word list via LPRINT, then reveals placed words in inverse video. 6. **Subroutine** (line 800): COPY + LPRINT line feeds, then RETURN. 7. **Save lines** (lines 865, 9998): Two SAVE statements for persistence. ### Grid and Data Structures The grid size `D` is fixed at 20 (line 210). Two main arrays are used: - `C$(A+5, (LEN B$)+5)` — a 2D string array holding all entered words, dimensioned with a small buffer beyond the user-specified count and longest word length. - `H$(D,D)` — a 20×20 character array representing the puzzle grid. A space character indicates an empty cell. - `K(LEN J$, 5)` — a temporary numeric array storing the X,Y coordinates of each letter of the current word being placed, used to commit positions only after a full valid placement is confirmed. ### Direction Encoding Word direction is encoded as two independent step values `Z` and `W` (not to be confused with the loop variable `Z` in the intro), each chosen from {−1, 0, 1}. Lines 330–370 generate them by picking a random integer 0–2 and mapping 2 to −1, giving eight possible directions plus the degenerate (0,0) case which is rejected at line 350. This covers all eight compass directions for diagonal, horizontal, and vertical word placement. ### Collision Detection and Retry Logic Lines 430–440 implement placement validation. If a letter would fall outside the 1–20 grid bounds, or if the target cell is already occupied by a *different* letter, the entire word placement restarts from line 290 with a new random position and direction. Crucially, the two-phase approach — first computing all coordinates into `K`, then committing them to `H$` only at lines 490–540 — prevents partial writes from corrupting the grid on a failed attempt. ### Notable Techniques - **POKE 23609,20 and POKE 23658,8** (line 4): Sets the key repeat delay and enables CAPS LOCK, a common configuration poke for input-heavy programs. - **Random letter fill**: `CHR$(INT(RND*26)+65)` generates a random ASCII uppercase letter (A–Z), using ASCII rather than the native character set CODE offset. - **Two-phase word commit**: The `K` array decouples coordinate calculation from grid writing, enabling clean rollback on collision without needing to undo partial writes. - **Answer suppression**: The variable `R$` captured at line 40 is checked throughout the placement loop (line 520); if “N”, letters are placed silently into `H$` without being printed. - **Decorative border** (line 656): A single FOR loop draws asterisks on all four edges simultaneously using multiple AT clauses in one PRINT statement. - **LPRINT output** (lines 662–665, 800): Supports a ZX Spectrum printer interface for producing a physical copy of both the grid and the word list. ### Bugs and Anomalies - **Variable name collision**: The intro loop at line 2 uses `Z` and `W` as loop counters. The same names are later used for direction step values in the placement phase (lines 330–370). Since the intro loop completes before placement begins, this does not cause a runtime error, but it is a potential source of confusion. - **Line 165 skip logic**: When a word entered at line 160 is longer than the first word `B$`, the program jumps to line 180 (skipping the PRINT at line 170), but still stores the over-length word in `C$`. The DIM at line 120 was sized based on `LEN B$`, so storing a longer word will be silently truncated by the string array, potentially corrupting the word. - **Space handling**: Lines 400 and 500 skip spaces in words, allowing multi-word phrases. However, a space in a word will leave a gap in placement coordinates in `K`, and the corresponding `K(L,1)` and `K(L,2)` will be zero from DIM initialization, which could cause an out-of-range error at line 510 if not skipped correctly — though line 500 does guard against this. - **GO TO 7** (line 790): The program loops back to line 7 on “play again,” but line 7 is `CLS` — this bypasses the word input and immediately re-enters the placement phase with stale data in `C$`. The correct restart target is likely line 10 or 80. - **`Z$` reuse**: The decorative string `Z$="WORDSQUARE"` set at line 201 is overwritten by INPUT statements later (lines 660, 661, 670, etc.), but by that point the decorative use is complete, so this causes no functional error. ### Line Reference Summary | Lines | Purpose | | --- | --- | | 2–7 | Animated intro, screen configuration | | 10–80 | Prompt for answer visibility preference and word count | | 100–190 | Word entry loop, populate `C$` | | 200–270 | Initialize display grid and `H$` array | | 280–550 | Word placement loop with collision detection | | 560–656 | Fill empty cells, draw border, offer COPY | | 660–665 | Optional LPRINT of word list | | 670–795 | Answer reveal and replay prompt | | 800 | COPY subroutine | | 865, 9998 | SAVE statements | ## Source Code ``` 1 REM WORDSQUARE TRANSLATED BY ME FROM HARTNELL BOOK, 51 PROGRAMS FOR T1000, THEN POLISHED BY JAMES DUPUY OF GREATER CLEVELAND TSUG 2 FOR Z=1 TO 15: FOR W=1 TO 15 3 BEEP .01,Z: PRINT "WORDSQUARE WORDSQUARE";: NEXT Z: NEXT W 4 POKE 23609,20: POKE 23658,8 5 PAUSE 100: CLS 6 BRIGHT 1: BORDER 5 7 CLS 10 PRINT "IF YOU DO NOT WANT TO SEE THE ANSWERS, THEN PRESS NOW. OTHERWISE, PRESS ANY KEY." 40 LET R$=INKEY$ 50 IF R$ ="" THEN GO TO 40 60 CLS 70 PRINT AT 10,4; FLASH 1;"WORD SQUARE WORD SQUARE" 80 INPUT "HOW MANY WORDS? (5-20):";A: IF A<5 OR A>20 THEN GO TO 80 100 PRINT AT 19,0;"ENTER LONGEST WORD." 110 INPUT B$ 120 DIM C$(A+5,(LEN B$)+5) 130 LET C$(1)=B$ 135 CLS : PRINT "1: ";B$ 140 FOR C=2 TO A 150 PRINT AT 21,0;"ENTER WORD NUMBER ";C 160 INPUT D$ 165 IF LEN D$>LEN B$ THEN GO TO 180 170 PRINT AT C-1,0;C;": ";D$ 180 LET C$(C)=D$ 190 NEXT C 200 CLS 201 LET Z$="WORDSQUARE" 205 FOR C=2 TO 20 STEP 2: PRINT AT C,30; INVERSE 1;Z$(C/2): NEXT C 210 LET D=20 220 FOR E=1 TO D 230 FOR F=1 TO D 240 PRINT AT E,F;"*" 250 NEXT F 260 NEXT E 270 DIM H$(D,D) 280 FOR Q=1 TO A 290 LET J$=C$(Q) 300 PRINT AT 0,0;J$ 310 LET X=INT (RND*D)+1 320 LET Y=INT (RND*D)+1 330 LET Z=INT (RND*3) 340 LET W=INT (RND*3) 350 IF Z=0 AND W=0 THEN GO TO 330 360 IF Z=2 THEN LET Z=-1 370 IF W=2 THEN LET W=-1 380 DIM K(LEN J$,5) 390 FOR L=1 TO LEN J$ 400 IF J$(L)=" " THEN GO TO 480 410 LET X=X+Z 420 LET Y=Y+W 430 IF X<1 OR X>D OR Y<1 OR Y>D THEN GO TO 290 440 IF (NOT H$(X,Y)=" ") AND (NOT (H$(X,Y)=J$(L))) THEN GO TO 290 450 LET K(L,1)=X 460 LET K(L,2)=Y 470 INVERSE 1: PRINT AT 0,L-1;CHR$ (CODE J$(L)) 480 NEXT L 485 INVERSE 0 490 FOR M=1 TO LEN J$ 500 IF J$(M)=" " THEN GO TO 540 510 LET H$(K(M,1),K(M,2))=J$(M) 520 IF R$="N" THEN GO TO 540 530 PRINT AT K(M,1),K(M,2);J$(M) 535 BEEP .05,30 540 NEXT M 550 NEXT Q 560 PRINT AT 0,0;" " 570 FOR N=1 TO D 580 FOR P=1 TO D 590 IF NOT H$(N,P)=" " THEN PRINT AT N,P;CHR$ (CODE H$(N,P)): GO TO 620 600 LET P$=CHR$ (INT (RND*26)+65) 610 PRINT AT N,P;P$ 620 BEEP .003,50 640 NEXT P 650 NEXT N 655 BEEP .5,20 656 FOR T=0 TO 21: PRINT AT 0,T;"*";AT 21,T;"*";AT T,0;"*";AT T,21;"*": NEXT T 660 INPUT FLASH 1;"PRESS ENT FOR COPY";Z$: IF Z$="" THEN GO SUB 800 661 INPUT "PRINT WORDS?((ENT OR N)";Z$: IF Z$="N" THEN PAUSE 30: GO TO 670 662 LPRINT '"THE WORDS TO LOOK FOR ARE:"' 663 FOR U=1 TO A: LPRINT U;": ";C$(U): NEXT U 665 LPRINT ''' 670 INPUT FLASH 1;"PRESS ENT FOR ANSWERS. "; LINE Z$ 700 FOR N=1 TO D 710 FOR P=1 TO D 720 IF H$(N,P)=" " THEN GO TO 740 725 BEEP .1,25 730 INVERSE 1: PRINT AT N,P;CHR$ (CODE H$(N,P)) 740 NEXT P 750 NEXT N 760 INVERSE 0 770 INPUT FLASH 1;"PRESS ENT FOR COPY OF ANSWERS."; LINE Z$: IF Z$="" THEN GO SUB 800 790 INPUT "PLAY AGAIN? (Y/N) ";Z$: IF Z$<>"N" THEN CLEAR : GO TO 7 795 STOP 800 COPY : LPRINT ''': RETURN 850 STOP 865 SAVE "WORDSQUARE": GO TO 2 9998 SAVE "WORDSQUARE" LINE 2 ```