--- title: "Battle" id: 55958 type: "computer_media" slug: "battle" url: "http://localhost/computer_media/battle/" markdown_url: "http://localhost/computer_media/battle.md" published_at: "2024-07-14T12:40:51+00:00" modified_at: "2026-03-30T21:41:04+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/07/SCR-20240714-ictf.png" excerpt: "A board game where you and the computer trade diagonal captures on a block-graphic grid — enter coordinates to move, and race to six captures first." 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/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 55923 title: "Timex Sinclair Public Domain Library Tape 2003" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-2003/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Battle%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198" images: - url: "http://localhost/wp-content/uploads/2024/07/SCR-20240714-ictf.png" media_type_tags: "Game" --- This program implements a two-player diagonal-move board game played on a 9×9 grid using block graphics for the border and “X” versus “O” pieces. The board is stored in a 12×13 string array S$, with an 11-character-wide border representation built from a separate 10×11 string array B$ using Spectrum block graphic characters (▄, █, ▟, ▘). The human player inputs moves as two-digit coordinates (row×10+column), and the computer’s AI subroutine at line 1000 scans the board for an X piece that has a valid diagonal capture of an O piece, setting flag FL and direction offsets G and H. Score tracking variables HS (human score) and CS (computer score) count captured pieces, with a win condition at 6 captures. *** ## Program Analysis ### Program Structure The program is divided into three logical sections: board initialization (lines 6–132), the main game loop (lines 135–320), the computer AI subroutine (lines 1000–1129), and the display subroutine (lines 1130–1180). A `SAVE` command is placed at line 2000 for archiving purposes. 1. **Lines 6–132:** Build the graphical border in `B$`, then copy each character into the game state array `S$`. 2. **Lines 135–320:** Main game loop — display board, accept player move, validate it, update state, invoke AI. 3. **Lines 1000–1129:** Computer move subroutine — scans for an X piece with an adjacent A$ neighbor and sets direction offsets. 4. **Lines 1130–1180:** Display subroutine — redraws the full board and score line. ### Board Representation The playing field is encoded using two string arrays. `B$(10,11)` stores the visual rows of the border/grid using Spectrum block graphic characters: `\.'` (▖), `\::` (█), `\:.` (▙), `\':.` (▟), `\'.` (▚), and `\.'` (▖). The border rows use characters like `1`–`9` as column labels, and rows 1 and 10 serve as top and bottom decorative borders. The actual game state array `S$(12,13)` is slightly oversized to allow safe ±1 index arithmetic without boundary errors. At line 125, the copy loop uses `C$(B TO )(1)` — a slice-then-index idiom — to extract a single character from position B of the cached row string `C$`, avoiding repeated indexing into the 2D array `B$` inside the inner loop. ### Move Input and Validation The player encodes a board position as a two-digit number: tens digit = row, units digit = column. Lines 167–175 decode this with integer division and modulo arithmetic. The move is validated at line 180: both the row and column differences between source and destination must be exactly 1 (diagonal adjacency), enforced with `ABS(A-C)<>1 OR ABS(B-D)<>1`. There is no check that the source square actually contains the player’s piece (“O”), so the player could technically move from any non-border square. ### Computer AI Subroutine (Lines 1000–1120) The AI scans the board sequentially, column by column within each row, looking for an “X” piece. For each X found, it checks all four diagonal neighbors for the target piece type stored in `A$`. The direction variables `G` and `H` are set according to which diagonal contains the match. Flag `FL=1` is raised and the routine returns as soon as a valid move is found. The subroutine is called twice in the main loop: first with `A$="O"` to find a capture move (line 255), and if none is found (`FL=0`), again with `A$=" "` to find any move to an empty square (line 265). This gives the computer a simple capture-first priority heuristic. | Variable | Role | | --- | --- | | `E, F` | Row/column of the X piece found by AI | | `G, H` | Row/column direction offsets (+1 or -1) for the move | | `FL` | Flag: 1 if a valid move was found | | `HS` | Human score (captures) | | `CS` | Computer score (captures) | ### Notable Techniques - The `S$` array is dimensioned `DIM S$(12,13)` rather than `(10,11)`, providing a one-cell buffer on all sides so the AI’s `E±1` / `F±1` accesses never go out of bounds. - Line 135 uses `RND>0.5` to randomly decide whether to pre-place an X at position (5,5) and clear (5,7), adding slight positional variety at the start. - The display subroutine uses `PRINT AT 0,0;` to home the cursor without clearing the screen, then overwrites the previous board in place — a flicker-free redraw technique. - Line 125’s `C$(B TO )(1)` is a character extraction idiom: `C$(B TO )` produces a substring from position B to the end, and `(1)` takes its first character — equivalent to `C$(B)` on some BASICs but here used as a workaround for single-character extraction from a slice. ### Bugs and Anomalies - Line 1145 uses lowercase `a` and `b` in `PRINT S$(a,b);` — on the Spectrum/TS2068, variable names are case-sensitive in the token stream; these should be uppercase `A` and `B` to match the loop variables declared at lines 1132 and 1140. This is likely a transcription artifact. - The win condition checks at lines 157 and 245 print a win message but do not halt the game — they fall through to the next input prompt. The variable `SW` referenced in both win messages is never assigned, so it would print as 0. - Line 1085 returns from within the scan loop with `E` and `F` pointing to a found piece, but does not reset `E`, `F`, `G`, `H` on entry — lines 1000–1003 do this explicitly each call, which is correct. - No check is made that the destination square is empty before placing the player’s piece at line 221, allowing overwriting of border characters or the opponent’s pieces. ## Source Code ``` 6 DIM B$(10,11) 10 LET B$(1)="\.'123456789\'." 20 LET B$(2)="1X\::X\::X\::X\::X1" 30 LET B$(3)="2\::X\::X\::X\::X\::2" 40 LET B$(4)="3X\::X\::X\::X\::X3" 50 LET B$(5)="4\::X\::X\::X\::X\::4" 60 LET B$(6)="5 \:: \:: \:: \:: 5" 70 LET B$(7)="6\::O\::O\::O\::O\::6" 80 LET B$(8)="7O\::O\::O\::O\::O7" 90 LET B$(9)="8\::O\::O\::O\::O\::8" 100 LET B$(10)="\'.123456789\.'" 102 LET HS=0 105 LET CS=0 110 DIM S$(12,13) 115 FOR A=1 TO 10 117 LET C$=B$(A) 120 FOR B=1 TO 11 125 LET S$(A,B)=C$(B TO )(1) 130 NEXT B 132 NEXT A 135 IF RND>.5 THEN GO TO 150 140 LET S$(5,5)="X" 141 LET S$(5,7)=" " 150 GO SUB 1130 155 PRINT 157 IF CS=6 THEN PRINT "I WIN ";SW 160 PRINT AT 15,0;"FROM?" 165 INPUT MOVE 166 PRINT AT 15,4;" ";MOVE;" TO?" 167 LET A=INT (MOVE/10) 168 LET B=MOVE-10*A 170 INPUT MOVE 171 PRINT AT 15,0;" " 172 LET C=INT (MOVE/10) 175 LET D=MOVE-10*C 180 IF ABS (A-C)<>1 OR ABS (B-D)<>1 THEN GO TO 160 190 IF S$(C+1)(D+1)="X" THEN LET HS=HS+1 210 LET S$(A+1)(B+1)=" " 221 LET S$(C+1)(D+1)="O" 240 GO SUB 1130 245 IF HS=6 THEN PRINT "YOU WIN ";SW 250 LET A$="O" 255 GO SUB 1000 257 IF FL=1 THEN GO TO 300 260 LET A$=" " 265 GO SUB 1000 300 LET S$(E)(F)=" " 305 IF S$(E+G)(F+H)="O" THEN LET CS=CS+1 310 LET S$(E+G)(F+H)="X" 320 GO TO 150 1000 LET E=2 1001 LET F=2 1002 LET G=0 1003 LET H=0 1010 LET FL=0 1020 IF S$(E)(F)<>"X" THEN GO TO 1100 1040 IF S$(E+1)(F+1)=A$ OR S$(E+1)(F-1)=A$ THEN LET G=1 1050 IF S$(E+1)(F+1)=A$ OR S$(E-1)(F+1)=A$ THEN LET H=1 1060 IF S$(E-1)(F+1)=A$ OR S$(E-1)(F-1)=A$ THEN LET G=-1 1070 IF S$(E+1)(F-1)=A$ OR S$(E-1)(F-1)=A$ THEN LET H=-1 1080 IF G<>0 AND H<>0 THEN LET FL=1 1085 IF FL=1 THEN RETURN 1100 LET E=E+1 1101 IF E>10 THEN LET F=F+1 1102 IF E>10 THEN LET E=2 1110 IF F>11 THEN RETURN 1120 GO TO 1010 1129 STOP 1130 PRINT AT 0,0; 1132 FOR A=1 TO 10 1135 PRINT 1140 FOR B=1 TO 11 1145 PRINT S$(a,b); 1150 NEXT B 1155 NEXT A 1160 PRINT 1165 PRINT 1170 PRINT "ME: ";Cs;" YOU: ";HS 1180 RETURN 2000 SAVE "BATTLE" 2010 STOP ```