--- title: "Devon Demon" id: 56522 type: "computer_media" slug: "devon-demon" url: "http://localhost/computer_media/devon-demon/" markdown_url: "http://localhost/computer_media/devon-demon.md" published_at: "2024-08-11T23:02:14+00:00" modified_at: "2026-04-03T07:59:04+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/08/SCR-20240810-krlr.png" excerpt: "A complete diagonal draughts game where the computer hunts your pieces, with board state hidden inside REM statements and manipulated purely through memory POKEs." 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_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/Devon%20Demon%20%28198x%29%28TS1000%29%28US%29%28Cassette%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/08/SCR-20240810-krlr.png" - url: "http://localhost/wp-content/uploads/2024/08/SCR-20240810-krjc.png" - url: "http://localhost/wp-content/uploads/2024/08/DevonDemon.jpg" media_type_tags: "Game" --- This program implements a diagonal draughts (checkers) variant called “Devon Demon,” a two-player abstract strategy game where the human plays “X” and the computer plays “O.” The board state is stored directly in memory starting at address 16513, using PEEK and POKE to read and write piece positions, with character codes 52, 61, 27, and 128 representing different board cell states. Lines 30–50 use a self-modifying bootstrap technique: they copy 36 bytes of board-state data from the REM statements at lines 10–20 (offset +42 from address 16514) into the working board area. The computer’s move logic uses a direction array B() with offsets ±5 and ±7 corresponding to diagonal moves on a 6-column board, and includes boundary detection and a simple capture-seeking heuristic. *** ## Program Analysis ### Program Structure The program is divided into three broad phases: 1. **Bootstrap (lines 10–55):** Copies initial board data from the REM statements into the working board area in memory, then jumps to the title/instructions routine. 2. **Instructions (lines 1000–1090):** Displays the game title and rules, waits for NEWLINE, then jumps to game initialisation at line 60. 3. **Game loop (lines 60–710):** Initialises state, handles display, processes human and computer moves, and detects win conditions. ### Bootstrap and REM-Based Data Storage Lines 10 and 20 contain REM statements whose character data encodes the initial board layout. The loop at lines 30–50 copies 36 bytes from address `16514+42 = 16556` (inside the REM statement body) to addresses `16514` through `16549`, which form the working board array starting at `Z=16513` (so cells are at `Z+1` through `Z+36`). This is a classic ZX81 technique for embedding binary or character data inside REM lines to avoid the overhead of DATA/READ statements. ### Board Representation The board is a 6×6 grid stored as 36 consecutive bytes in RAM from address `Z+1` to `Z+36`. Character codes encode cell contents: | Code | Meaning | | --- | --- | | 52 | Computer piece (“O”) | | 61 | Human piece (“X”) | | 27 | Empty square | | 128 | Temporary marker during computer move animation | The board is displayed by printing `CHR$ PEEK (Z+C)` for each cell, relying on the ZX81 character set to render the appropriate glyphs. Column labels A–F are derived by printing `CHR$ (C/6+37)` at every sixth cell (line 240), and row numbers “1 2 3 4 5 6” are printed at line 260. ### Move Input Parsing The human enters a four-character string such as “A1B2”. Line 340 decodes the source square: `D = 6*(CODE A$(1)-38) + CODE(A$(2))-28`. Since “A” has ZX81 code 38, `CODE A$(1)-38` gives the column index 0–5, multiplied by 6 for the row offset. `CODE(A$(2))-28` converts the digit character (“1″=29 in ZX81) to 1–6. Line 350 performs the same calculation for the destination square into `E`. If the destination holds a computer piece (code 52), the human’s score is incremented (line 360). ### Direction Array and Diagonal Movement Array `B()` holds four diagonal offsets for a 6-column board: - `B(1)=5` — diagonal down-left - `B(2)=7` — diagonal down-right - `B(3)=-5` — diagonal up-right - `B(4)=-7` — diagonal up-left These offsets reflect the fact that adjacent diagonal cells differ by 5 or 7 positions in the linear board array on a 6-wide grid (not the expected ±5/±7 for a standard 8-wide board, since rows are 6 cells wide here). ### Computer AI The computer’s move selection (lines 490–590) works as follows: 1. Pick a random board cell `F`; retry if it does not contain a computer piece (code 52). 2. With 80% probability, select a random direction `M` from 1–4 (line 530). 3. Apply boundary guards (lines 540–550) to prevent wrapping off the left or right edges of the board. 4. At line 560, check if the cell at `F+B(M)` is an empty square (27) and the cell beyond it (`F+2*B(M)`) is not a human piece (61) — if this multi-hop condition is met, jump directly to the capture/move execution at line 620. 5. If the direction is invalid, increment `M` and try the next; after exhausting all four directions, retry with a new random piece (up to 200 attempts via line 590). Lines 450–460 also check whether any computer piece can immediately capture a human piece (land on a cell containing 61), providing a simple opportunistic capture before the random-move fallback. ### Win Detection The human wins when `S=4` (four computer pieces captured, line 410). The computer wins when `N=4` (four human pieces captured, line 650). Both conditions print a result message and STOP. ### Notable Techniques and Anomalies - **SLOW/FAST switching:** The program toggles between SLOW (display-on) and FAST (display-off) modes around display and computation phases to balance responsiveness and speed. - **Score variable redundancy:**`LET S=0` appears twice (lines 80 and 90), which is harmless but redundant. - **Loop variable reuse:** Variable `M` is used both as a direction index within the AI loop and as a loop counter in FOR/NEXT at line 440, which could cause confusion but works because the FOR loop at 440 is always completed before `M` is reassigned at line 490. - **Boundary detection coverage:** The edge guards at lines 540–550 only cover specific column positions (F=6,16,30 and F=7,19,31), which correspond to the rightmost and leftmost cells of rows on a 6-wide board. This approach is functional but fragile—it would fail for board sizes other than 6. - **INKEY$ wait idiom:** Lines 1060–1070 first flush any held keypress, then wait for NEWLINE (CHR$ 118), a standard ZX81 debounce pattern. - **Counter K:**`K` is incremented at line 510 during the AI’s random-piece search and checked at line 590 (`IF M<200`), but `M` rather than `K` is the variable tested — this means the 200-iteration guard on line 590 actually checks the direction index, not the attempt count, making it effectively always true for a legal board state. The intended exhaustion guard on `K` is never used. ## Source Code ``` 10 REM .X.X.XX.X.X..............O.O.OO.O.O. 20 REM .X.X.XX.X.X..............O.O.OO.O.O. 30 FOR K=16514 TO 16549 40 POKE K,PEEK (K+42) 50 NEXT K 54 SLOW 55 GOTO 1000 60 LET N=0 70 LET Z=16513 80 LET S=0 90 LET S=0 100 DIM B(4) 110 LET B(1)=5 120 LET B(2)=7 130 LET B(3)=-5 140 LET B(4)=-7 150 SLOW 160 LET K=0 170 GOSUB 200 180 FAST 190 GOTO 490 200 PRINT AT 5,0;"TIMEX-";N,"HUMAN-";S 210 PRINT 220 FOR C=1 TO 36 230 PRINT CHR$ PEEK (Z+C);" "; 240 IF 6*(INT (C/6))=C THEN PRINT CHR$ (C/6+37) 250 NEXT C 260 PRINT "1 2 3 4 5 6" 270 FOR H=1 TO 30 280 NEXT H 290 RETURN 300 GOSUB 200 310 SLOW 320 PRINT "YOUR MOVE?" 330 INPUT A$ 340 LET D=6*(CODE A$(1)-38)+CODE (A$(2))-28 350 LET E=6*(CODE A$(3)-38)+CODE (A$(4))-28 360 IF PEEK (E+Z)=52 THEN LET S=S+1 370 POKE (D+Z),27 380 POKE (E+Z),61 390 GOSUB 200 400 FAST 410 IF S=4 THEN GOTO 600 420 LET K=0 430 FOR F=1 TO 36 440 FOR M=1 TO 4 450 IF PEEK (F+Z)=52 AND PEEK (F+Z+B(M))=61 THEN LET N=N+1 460 IF PEEK (F+Z)=52 AND PEEK (F+Z+B(M))=61 THEN GOTO 620 470 NEXT M 480 NEXT F 490 LET M=1 500 LET F=INT (RND*36)+1 510 LET K=K+1 520 IF PEEK (F+Z)<>52 THEN GOTO 500 530 IF RND>.2 AND M<3 THEN LET M=4-(INT (RND*4)) 540 IF (F=6 OR F=16 OR F=30) AND (M=2 OR M=3) THEN GOTO 570 550 IF (F=31 OR F=19 OR F=7) AND (M=1 OR M=4) THEN GOTO 570 560 IF PEEK (F+Z+B(M))=27 AND PEEK (F+Z+2*B(M))<>61 THEN GOTO 620 570 LET M=M+1 580 IF M<5 THEN GOTO 540 590 IF M<200 THEN GOTO 490 600 PRINT "YOU WIN" 610 STOP 620 SLOW 630 POKE (F+Z+B(M)),128 640 GOSUB 200 650 IF N=4 THEN GOTO 700 660 POKE (F+Z),27 670 POKE (F+Z+B(M)),52 680 GOTO 300 700 PRINT "I WIN " 710 STOP 1000 PRINT TAB 10;"DEVON DEMON" 1010 PRINT ,,"IN THIS GAME,YOU MUST CAPTURE 4 OF THE 1000S PIECES.IT IS ""O"",AND YOU ARE ""X""" 1020 PRINT ,,"YOU CAPTURE BY LANDING ON TOP OFTHE PIECE,AND YOU MOVE ALONG THEDIAGONALS,BACKWORDS AND FORWARDS" 1030 PRINT ,,"TO MOVE,ENTER THE LETTER AND NUMBER OF PIECE TO MOVE,AND THEN,AT THE SAME TIME.THE LETTER ANDNUMBER OF THE PLACE TO MOVE TO E.G.:" 1040 PRINT "A1B2---YOU WOULD MOVE THE PIECE ON A1 TO B2" 1050 PRINT ,,TAB 5;"PRESS NEWLINE NOW" 1060 IF INKEY$<>"" THEN GOTO 1060 1070 IF INKEY$<>CHR$ 118 THEN GOTO 1070 1080 CLS 1090 GOTO 60 ```