--- title: "Knights Move" id: 57243 type: "computer_media" slug: "knights-move" url: "http://localhost/computer_media/knights-move/" markdown_url: "http://localhost/computer_media/knights-move.md" published_at: "2024-10-04T07:11:53+00:00" modified_at: "2026-03-30T21:19:05+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/133_KniM.png" excerpt: "Can you guide a chess knight to every square on the board exactly once? This BASIC puzzle challenges you to complete the classic Knight's Tour in 64 moves." 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 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56734 title: "Timex Sinclair Public Domain Library Tape 1003" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1003/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/133_KniM.png" media_type_tags: "Game" --- This program implements the Knight’s Tour puzzle, where the player must move a chess knight to every square on an 8×8 board without revisiting any square. The board is drawn using alternating inverse-video and normal characters to simulate a chequered pattern, and move numbers are printed directly onto the board at calculated screen positions using AT coordinates. Input is taken as a two-character string (e.g. “34” for row 3, column 4), with the subroutine at line 410 handling validation of range and already-visited squares. The program runs in FAST mode during board setup and switches to SLOW for interactive play, a common ZX81 technique to speed up the initial screen draw. *** ## Program Analysis ### Program Structure The program divides cleanly into several phases: 1. **Initialisation (lines 10–160):** Dimensions the 8×8 board array, draws the chequered grid, and zeroes all cells. 2. **Starting position (lines 170–270):** Prompts the player for a starting square, validates it via the subroutine, marks it, and records the position. 3. **Main game loop (lines 280–400):** Repeatedly asks for the next move, validates it, checks knight-move legality, and updates the board until all 64 squares are visited or the player quits. 4. **Input/validation subroutine (lines 410–480):** Parses the two-character input string, range-checks both coordinates, and rejects already-visited squares. 5. **End/replay (lines 490–520):** Offers replay on NEWLINE or halts on any other input. ### Board Display The chequered board is constructed from two alternating string patterns. `A$` (line 20) contains inverse-video characters forming one row style, and `B$` (line 30) contains the complementary row. These are printed in a loop (lines 80–100) using `TAB` and the `;;` double-semicolon idiom to suppress spacing. Move numbers are placed directly on the board using `PRINT AT L*2, C*3+3`, mapping logical board coordinates to screen positions. A trailing space (line 240) is printed when the move count is less than 10 to keep single-digit numbers tidy. ### Input Parsing Player input is a two-character string such as `"35"`, parsed at lines 430–440 using `VAL C$(1)` and `VAL C$(2)` to extract the row and column digits individually. This avoids any need for numeric input or comma-separated values, keeping entry fast. Entering `"0"` at line 340 allows the player to quit mid-game. ### Knight-Move Validation Lines 370–380 check whether the proposed square is a legal knight’s move from the current position `(L1, C1)`. The logic attempts to replicate the two valid L-shaped move families: - Line 370: `L=L1±2` paired with `C=C1±1` - Line 380: `L=L1±1` paired with `C=C1±2` However, these conditions contain a well-known ZX81 BASIC operator-precedence bug. The expression `L=L1-2 OR L=L1+2 AND C=C1-1 OR C=C1+1` is evaluated as `L=L1-2 OR (L=L1+2 AND C=C1-1) OR C=C1+1` because `AND` binds more tightly than `OR`. This means a move is accepted whenever *either* the column offset is ±1 (regardless of the row) or the row offset is ±2 with column offset −1. The correct check would require parentheses grouping both row and column conditions together. The same flaw appears on line 380. As a result, several illegal moves will be accepted and some valid ones may behave unexpectedly. ### Array Usage and State Tracking The 2D array `B(8,8)` acts as a visited-squares bitmap: cells are set to `1` at line 270 when visited, and the subroutine at line 452 rejects any square where `B(L,C)=1`. The move counter `M` serves double duty as both a display label and a win condition (`M=64` at line 280). ### FAST/SLOW Usage `FAST` is engaged at line 50 before the board is drawn, suppressing the display during the computationally intensive screen-building loop. `SLOW` is restored at line 170 before interactive input begins, restoring the live display for the player. ### Notable Idioms and Anomalies | Line | Idiom / Issue | | --- | --- | | `90` | `;;` (double semicolon) suppresses the automatic space between `PRINT` items | | `210` | Sentinel value `L=9` is used to signal invalid input from the subroutine — a classic ZX81 out-of-band return technique | | `310`, `410` | Fixed-width space strings are used to blank previous messages rather than `CLS`, preserving the board | | `370–380` | Operator precedence bug makes knight-move validation incorrect (see above) | | `510` | An empty `INPUT` response (bare NEWLINE) returns `C$=""`, used as the replay trigger | ## Source Code ``` 1 REM KNIGHTS MOVE 10 DIM B(8,8) 20 LET A$="%I%-%-%I%-%-%I%-%-%I%-%-%I%-%-%I%-%-%I%-%-%I%-%-%I" 30 LET B$="I% % I% % I% % I% % I% % I% % I% % I% % I" 40 CLS 50 FAST 60 PRINT TAB 6;"1 2 3 4 5 6 7 8" 70 PRINT TAB 5;A$ 80 FOR L=1 TO 8 90 PRINT TAB 3;;L;" ";B$;TAB 5;A$ 100 NEXT L 110 FOR L=1 TO 8 120 FOR C=1 TO 8 130 LET B(L,C)=0 140 NEXT C 150 NEXT L 160 LET M=0 170 SLOW 180 PRINT AT 20,0;"WHERE DO YOU WISH TO BEGIN?" 190 INPUT C$ 200 GOSUB 410 210 IF L=9 THEN GOTO 180 220 LET M=M+1 230 PRINT AT L*2,C*3+3;M 240 IF M<10 THEN PRINT AT L*2,C*3+4;" " 250 LET L1=L 260 LET C1=C 270 LET B(L,C)=1 280 IF M<64 THEN GOTO 310 290 PRINT AT 20,0;"CONGRATULATIONS" 300 GOTO 490 310 PRINT AT 19,0;" 10 SPACES " 320 PRINT AT 20,0;"WHERE DO YOU WISH TO GO NEXT?" 330 INPUT C$ 340 IF C$="0" THEN GOTO 490 350 GOSUB 410 360 IF L=9 THEN GOTO 320 370 IF L=L1-2 OR L=L1+2 AND C=C1-1 OR C=C1+1 THEN GOTO 220 380 IF L=L1-1 OR L=L1+1 AND C=C1-2 OR C=C1+2 THEN GOTO 220 390 PRINT AT 19,0;"IMPOSSIBLE" 400 GOTO 320 410 PRINT AT 20,0;" 28 SPACES " 420 IF LEN C$<>2 THEN GOTO 470 430 LET L=VAL C$(1) 440 LET C=VAL C$(2) 450 IF L<1 OR L>8 OR C<1 OR C>8 THEN GOTO 460 452 IF B(L,C)=1 THEN GOTO 460 454 RETURN 460 LET L=9 470 PRINT AT 19,0;"IMPOSSIBLE" 480 RETURN 490 PRINT AT 21,0;"NL TO REPLAY" 500 INPUT C$ 510 IF C$="" THEN GOTO 40 520 STOP 600 SAVE "1013%3" 700 RUN ```