--- title: "Towers of Hanoi" id: 57506 type: "computer_media" slug: "towers-of-hanoi" url: "http://localhost/computer_media/towers-of-hanoi/" markdown_url: "http://localhost/computer_media/towers-of-hanoi.md" published_at: "2024-10-05T21:12:45+00:00" modified_at: "2026-03-30T21:17:39+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/towers-hanoi.jpeg" caption: "Vintage 1980s ZX Spectrum cassette inlay art, airbrush illustration of the Towers of Hanoi puzzle, three dramatic stone temple spires rising against a stormy violet sky, stacked golden discs glowing with neon rim-lighting transferring between towers, ancient mechanical precision, bold graphic design, dramatic low-angle perspective, saturated oranges and purples, a ghostly computer wireframe hand moving the largest disc, slightly garish hand-painted commercial art, British home computing aesthetic, circa 1983 --ar 3:4 --raw --v 6 Job ID: c99b6bcc-0185-496a-be8d-7ae6e75ecc61" excerpt: "A full Towers of Hanoi game with pixel-drawn discs, move validation, and a built-in computer solver that uses different peg-cycling strategies for odd and even disc counts." 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: 56737 title: "Timex Sinclair Public Domain Library Tape 1006" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1006/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/towers-hanoi.jpeg" caption: "Vintage 1980s ZX Spectrum cassette inlay art, airbrush illustration of the Towers of Hanoi puzzle, three dramatic stone temple spires rising against a stormy violet sky, stacked golden discs glowing with neon rim-lighting transferring between towers, ancient mechanical precision, bold graphic design, dramatic low-angle perspective, saturated oranges and purples, a ghostly computer wireframe hand moving the largest disc, slightly garish hand-painted commercial art, British home computing aesthetic, circa 1983 --ar 3:4 --raw --v 6 Job ID: c99b6bcc-0185-496a-be8d-7ae6e75ecc61" - url: "http://localhost/wp-content/uploads/2024/10/261_Twr.png" media_type_tags: "Game, Software" --- This program implements the Towers of Hanoi puzzle on a pixel-graphics display, supporting both manual play and an automated computer solver. The display uses PLOT/UNPLOT to draw disc representations on three pegs drawn with block graphics characters, and the game tracks move counts against the theoretical minimum of 2ⁿ−1. The computer solver at line 700 uses two different movement strategies depending on whether the disc count is odd or even, cycling through pairs of pegs (subroutine 900) until all discs reach peg 3. Disc size is encoded as an integer in a two-dimensional array D(N,3), with a stack-pointer array N(3) tracking the top disc on each peg. *** ## Program Analysis ### Program Structure The program is organized into clearly delineated sections accessed via `GOSUB`: | Line range | Purpose | | --- | --- | | 65–185 | Initialization: screen drawing, disc count input, stack setup | | 185–285 | Main game loop: manual move input and validation | | 300–382 | Move execution subroutine (calls UNPLOT and PLOT routines, updates arrays) | | 383–397 | Win/new-game handler | | 400–460 | PLOT subroutine — draws a disc on a peg | | 500–580 | UNPLOT subroutine — erases a disc from a peg | | 600–695 | Computer-solve prompt subroutine | | 700–780 | Computer solver — even disc count strategy | | 800–855 | Computer solver — odd disc count strategy | | 900–935 | Single legal move between a peg pair | | 940–960 | CLEAR, SAVE and RUN for auto-restart | ### Data Representation Two arrays manage the puzzle state. `N(3)` (declared at line 140, shadowing the scalar `N` which holds the disc count — note the name collision) acts as a stack pointer for each of the three pegs. `D(N,3)` is a 2-D array where `D(k,p)` holds the size of disc at position `k` on peg `p`. Disc sizes run from 1 (smallest) to `N` (largest). A value of 0 in `D` means the slot is empty. There is a notable naming collision: the variable `N` is first used as the disc count scalar, then `DIM N(3)` at line 140 replaces it with an array. Sinclair BASIC allows a scalar and an array to share the same letter, so both coexist, with `N` (scalar) remaining accessible as the disc count and `N(x)` being the stack-pointer array. ### Display Technique The three pegs are represented as vertical columns of block-graphic characters (`"\@@"` — solid block characters) drawn with `PRINT AT` in lines 75–86. Disc graphics are rendered with `PLOT`/`UNPLOT` in the pixel domain. The PLOT subroutine (lines 400–460) computes a horizontal centre `H = 20*Y - 6` for each peg and a vertical coordinate `V = 27 + 2*N(Y)`, then plots symmetric pairs of pixels outward from the centre for each unit of disc size. The UNPLOT subroutine mirrors this to erase. This gives discs a proportional pixel-width representation. ### Input Handling All key input uses the pattern of printing a flashing cursor (alternating plain `"?"` and inverse `"%?"`), then reading `CODE INKEY$` in a tight loop. This is a standard TS2068/Spectrum idiom for single-keypress input without blocking via `INPUT`. Digit keys 1–8 have `CODE` values 29–36 (Sinclair key codes), checked at lines 116 and 215/242. The ENTER/NEW-LINE key has code 118, checked at line 395. ### Computer Solver Algorithm The solver does not use recursion. Instead it exploits the cyclic property of the Tower of Hanoi: for an even number of discs, the optimal solution is achieved by repeatedly cycling moves in the order (1→2), (1→3), (2→3); for odd disc counts the order is (1→3), (1→2), (3→2). The cycle repeats until peg 3 holds all discs, then jumps to the win handler at line 383. Subroutine 900 (lines 905–935) implements a single legal move between pegs `P` and `Q`: it picks the peg with the smaller top disc (or the non-empty peg if one is empty) as the source, then calls the move execution subroutine at 300. ### Move Validation Manual moves are validated at lines 257–270. If the destination stack is non-empty (`N(Y)>0`) and the moving disc is not smaller than the top disc on the destination, the move is rejected as illegal. An empty destination always accepts any disc (line 257). Same-peg moves are caught at line 250. ### Win Condition The game checks `N(3)=N` (i.e., the stack pointer for peg 3 equals the total disc count) at lines 275 and 760/820. When satisfied, the win handler prints a prompt and waits for ENTER to start a new game via `GOTO 2` (a non-existent line, which causes the program to fall through to the next available line — line 65 — a well-known Sinclair BASIC technique). ### Notable Techniques - Flashing cursor using alternating plain and inverse `?` with `PRINT AT` over the same position. - Pixel-level disc drawing with `PLOT`/`UNPLOT` symmetrically around a peg centre. - Non-recursive computer solver using a fixed peg-pair cycling strategy differentiated by disc parity. - The `SAVE "1026%1"` at line 950 uses an inverse character in the filename as an auto-run marker. - `VAL (CHR$ C)` at lines 117 and 245 converts a key code to its digit value without a lookup table. ### Bugs and Anomalies - Line 270 uses `GOTO 200` and line 285 uses `GOTO 2`, both targeting non-existent lines; execution resumes at the next existing line (205 and 65 respectively). This is intentional Sinclair BASIC shorthand. - The subroutine nominally starting at line 300 actually begins at line 305, since there is no line 300. The `GOSUB 300` calls at lines 271 and 930 correctly fall through to line 305. - Line 703 resets `NN=0` for the computer solver run but this does not reset the on-screen counter until the first move is printed; a minor cosmetic inconsistency. - The win check at line 275 only tests `N(3)36 THEN GOTO 110 117 LET N=VAL (CHR$ C) 118 PRINT AT 11,18;N 119 LET NN=0 120 PRINT AT 13,0;"NUMBER OF MOVES = ";NN 121 PRINT AT 14,1;"MINIMUM NUMBER = ";2**N-1 140 DIM N(3) 145 DIM D(N,3) 150 LET Y=1 155 FOR I=1 TO N 160 LET N(Y)=I 165 LET D(N(Y),Y)=N+1-I 170 GOSUB 400 180 NEXT I 185 GOSUB 600 195 IF CC=62 THEN GOTO 700 205 PRINT AT 11,0;"MOVE FROM STACK TO STACK " 210 PRINT AT 11,16;"?" 211 PRINT AT 11,16;"%?" 214 LET C=CODE INKEY$ 215 IF C<29 OR C>31 THEN GOTO 210 216 LET X=VAL (CHR$ C) 220 IF N(X)>0 THEN GOTO 230 225 PRINT AT 12,0;"STACK ";X;" IS EMPTY " 226 GOTO 210 230 PRINT AT 11,16;X 231 PRINT AT 12,0;" " 235 PRINT AT 11,27;"?" 236 PRINT AT 11,27;"%?" 240 LET C=CODE INKEY$ 242 IF C<29 OR C>31 THEN GOTO 235 245 LET Y=VAL (CHR$ C) 250 IF Y=X THEN GOTO 235 255 PRINT AT 11,27;Y 257 IF N(Y)=0 THEN GOTO 271 260 IF D(N(X),X)D(N(Q),Q) THEN LET X=Q 925 IF X=Q THEN LET Y=P 930 GOSUB 300 935 RETURN 940 CLEAR 950 SAVE "1026%1" 960 RUN ```