--- title: "3-D TicTacToe" id: 71145 type: "computer_media" slug: "3-d-tictactoe" url: "http://localhost/computer_media/3-d-tictactoe/" markdown_url: "http://localhost/computer_media/3-d-tictactoe.md" published_at: "2026-08-31T09:23:10+00:00" modified_at: "2026-08-31T09:23:11+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/08/3d-tic-tac-toe.png" alt: "3-D TicTacToe screen" excerpt: "A fully playable two-player 3D Tic-Tac-Toe game on a 3×3×3 cube, with isometric block-graphic display and cumulative win scoring across all 49 possible lines." 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_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/3-D%20TicTacToe%20%28198x%29%28-%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/08/3d-tic-tac-toe.png" alt: "3-D TicTacToe screen" media_type_tags: "Game" --- # 3-D TicTacToe This program implements a three-dimensional Tic-Tac-Toe game on a 3×3×3 grid, where players designate moves by entering a layer letter (A, B, or C) followed by a position number (1–9). The board is rendered using block graphics to depict three overlapping grids in isometric-style perspective, representing front, middle, and rear planes. Cell coordinates for display are packed into strings X$ and Y$ and decoded at startup by extracting two-character substrings and converting them with VAL, an efficient data-storage technique for position tables. Win detection works by summing A() array values (1 for X, −1 for O) along 13 center-based symmetrical axes and 18 additional non-center lines defined by offset tables C() and R(), scoring accumulated wins in SX and SO rather than halting play after the first three-in-a-row. The first move is restricted from the center square (position 14, the cube’s center), and entering “R” resets the game. *** ### Program Structure The program is organized into a main loop with several subroutines: - Lines 1–4: Introduction and instructions display - Lines 5–90: Array and data initialization (dimensions, coordinate tables, win-line tables) - Lines 100–120: Game state reset - Lines 170–280: Main game loop (display, input, move processing) - Lines 390–395: Illegal move handler - Lines 500–580: Win-detection and scoring subroutine - Lines 800–810: Score incrementing helper - Line 900–905: Screen color setup subroutine - Lines 1000–1090: Board drawing subroutine - Lines 9997–9999: Stop, SAVE, and VERIFY ### Data Encoding in Strings A compact data-packing technique is used for screen coordinates and win-line definitions. `X$` and `Y$` (line 30–35) each hold 54 characters encoding 27 two-digit decimal numbers representing screen column and row positions for each of the 27 board cells. Similarly, `C$` and `R$` (lines 60–65) encode 18 two-digit values each, defining the center cell and offset for additional win-line checks. All values are decoded with `VAL X$(2*Z-1 TO 2*Z)`, a standard Sinclair BASIC string-slicing idiom that avoids the need for DATA/READ statements and saves memory. ### Board Representation The 3×3×3 cube is mapped to a flat array `A(27)`. Layers are addressed as offsets: A=cells 1–9, B=cells 10–18, C=cells 19–27. Player input converts a letter (A/B/C) to a base offset (0, 9, or 18) and adds the digit entered, producing a direct index into `A()`. Cell 14 is the geometric center of the cube; the program explicitly forbids occupying it on the first move (line 245). ### Win Detection Algorithm Win detection (lines 500–565) operates in two passes rather than checking all 49 lines explicitly: 1. **Center-symmetric lines (lines 515–530):** For Z=1 to 13, it sums `A(14-Z) + A(14) + A(14+Z)`. Because the center cell is always included and the 13 offsets cover all lines passing through the cube’s center, this elegantly handles all center-passing three-in-a-rows. 2. **Non-center lines (lines 535–565):** Uses `C(Z)` as the middle cell and `R(Z)` as the step offset. It checks both the line and its mirror (`V = 28 - C(Z)`) to cover symmetric non-center lines on the cube’s faces and diagonals. Rather than stopping at the first win, scoring accumulates into `SX` (X wins) and `SO` (O wins) across all 27 turns, and totals are printed after every move. This means the game is effectively a full-game scoring variant rather than a stop-at-first-win game. ### Notable Bugs and Anomalies - **Line 540 double-add bug:**`LET W=A(C(Z))+A(C(Z))+A(C(Z)+R(Z))` adds the middle cell twice instead of using `A(C(Z)-R(Z))+A(C(Z))+A(C(Z)+R(Z))`. This means the non-center line check is incorrect — it tests 2×middle + one neighbor rather than left + middle + right. This is a genuine bug that would cause missed or false win detections on non-center lines. - **No input validation beyond occupancy:** If the player enters an invalid layer letter or non-numeric digit, `VAL Z$(2)` may produce 0 or cause an error. No guard against single-character input for the digit is present. - **Center restriction only on move 1:** Line 245 prevents the center square on `N=1`, but the center is otherwise playable from move 2 onward. The instructions describe this rule correctly. - **Game does not end on a win:** Play always continues until all 27 cells are filled (`N=28` triggers a reset at line 205), at which point the game restarts without displaying final scores prominently. ### Board Drawing The subroutine at lines 1000–1090 draws an isometric-perspective three-layer board using block graphic characters. The three grids (A front, B middle, C rear) are overlaid with connecting lines rendered via block graphic escape sequences, giving visual depth. Cell labels 1–9 appear on each layer and layer letters A, B, C are shown on the right edge. The drawing is purely static — moves are plotted individually by printing “X” or “O” at precomputed `AT Y(Z),X(Z)` positions from the coordinate arrays. ### Screen and Color Setup Line 900 sets PAPER 6 (yellow), INK 1 (blue), and BORDER 6 at the start of each redraw. The FLASH attribute is used for feedback: `FLASH 1` is applied to the illegal-move warning at line 390, and `FLASH 0` is reset before each INPUT at line 200. ### Variable Summary | Variable | Purpose | | --- | --- | | `A(27)` | Board state: 0=empty, 1=X, -1=O | | `X(27)`, `Y(27)` | Screen column/row for each cell | | `C(18)`, `R(18)` | Center cell and step for non-center win lines | | `S` | Current player: 1=X, -1=O | | `N` | Move counter (1–27) | | `SX`, `SO` | Accumulated win-line counts for X and O | | `Z$` | Player input string (e.g., “A5”) | | `W` | Sum of three cells for win-line check | ## Source Code ``` 1 REM 3-D TIC TAC TOE:GO SUB 900 2 PRINT AT 3,0;" INITIALIZING-PLEASE STANDBY":POKE 23658,8 3 PRINT ,,"THE OBJECT IS TO GET AS MANY 3- IN-A-ROW LINES AS POSIBLE.",,,"REMEMBER: A IS THE FRONT- B IS THE MIDDLE AND C IS THE REAR." 4 PRINT ,,"THE FIRST PLAY MAY NOT BE THE CENTER SQUARE, ENTER LETTER 1ST.(A,B OR C) THEN A NUMBER (1-9)." :PAUSE 400 5 DIM A(27) 10 DIM C(18) 15 DIM R(18) 20 DIM X(27) 25 DIM Y(27) 30 LET X$="020814020814020814061218061218061218101622101622101622" 35 LET Y$="060606121212181818040404101010161616020202080808141414" 40 FOR Z=1 TO 27 45 LET X(Z)= VAL X$(2*Z-1 TO 2*Z) 50 LET Y(Z)= VAL Y$(2*Z-1 TO 2*Z) 55 NEXT Z 60 LET C$="020405050505060810111111111213131313" 65 LET R$="010301020304030109010809100903060912" 70 FOR Z=1 TO 18 75 LET C(Z)= VAL C$(2*Z-1 TO 2*Z) 80 LET R(Z)= VAL R$(2*Z-1 TO 2*Z) 90 NEXT Z 100 FOR Z=1 TO 27 105 LET A(Z)=0 110 NEXT Z 115 LET S=1 120 LET N=1 170 CLS 172 GO SUB 900 175 GO SUB 1000 180 IF S=1 THEN PRINT AT 2,24;" X TO GO" 185 IF S=-1 THEN PRINT AT 2,24;" O TO GO" 200 FLASH 0:INPUT Z$ 205 IF N=28 THEN GO TO 100 210 IF Z$(1)="R" THEN GO TO 100 215 IF Z$(1)="A" THEN LET Z=0 220 IF Z$(1)="B" THEN LET Z=9 225 IF Z$(1)="C" THEN LET Z=18 235 LET Z=Z+ VAL Z$(2) 240 IF A(Z) <>0 THEN GO TO 390 245 IF N=1 AND Z=14 THEN GO TO 390 250 LET A(Z)=S 255 LET N=N+1 260 IF S=1 THEN PRINT AT Y(Z),X(Z);"X" 265 IF S=-1 THEN PRINT AT Y(Z),X(Z);"O" 270 GO SUB 500 275 LET S=-S 280 GO TO 180 390 FLASH 1:PRINT AT 20,14;"ILLEGAL-TRY AGAIN" 395 GO TO 200 500 505 LET SX=0 510 LET SO=0 515 FOR Z=1 TO 13 520 LET W=A(14-Z)+A(14)+A(14+Z) 525 IF ABS W=3 THEN GO SUB 800 530 NEXT Z 535 FOR Z=1 TO 18 540 LET W=A(C(Z))+A(C(Z))+A(C(Z)+R(Z)) 545 IF ABS W=3 THEN GO SUB 800 550 LET V=28-C(Z) 555 LET W=A(V-R(Z))+A(V)+A(V+R(Z)) 560 IF ABS W=3 THEN GO SUB 800 565 NEXT Z 570 PRINT AT 20,0;"X=";SX;," O=";SO 580 RETURN 800 IF W=3 THEN LET SX=SX+1 803 IF W=-3 THEN LET SO=SO+1 810 RETURN 900 PAPER 6:INK 1 :BORDER 6 905 RETURN 1000 PRINT AT 0,6;"3-D TIC TAC TOE" 1004 PRINT AT 2,10;"1\''\''\''\''\''2\''\''\''\''\''3" 1006 PRINT AT 3,7;"\..\::\'' \..\::\''\ :" 1008 PRINT AT 4,6;"1 / 2 3 \ :" 1010 PRINT AT 5,3;"\..\::\'' / \..\::\'' \ :" 1012 PRINT AT 6,2;"1\''\''\''\''\''2\''\''\''\''\''3 \ :" 1014 PRINT AT 7,2;"\: / \ : \ :" 1016 PRINT AT 8,2;"\: 4 \ : 5 6 C" 1018 PRINT AT 9,2;"\: / \ : \ :" 1020 PRINT AT 10,2;"\: 4 / 5 \ : 6 \ : B" 1022 PRINT AT 11,2;"\: / \ : \ :" 1024 PRINT AT 12,2;"4 5/ 6 \ :A" 1026 PRINT AT 13,2;"\: / \ : \ :" 1028 PRINT AT 14,2;"\: 7///\ :/8/////9" 1030 PRINT AT 15,2;"\: /// \ : \..\::\''" 1032 PRINT AT 16,2;"\: 7 8 \ : 9" 1034 PRINT AT 17,2;"\: /// \ :\..\::\''" 1036 PRINT AT 18,2;"7\..\..\..\..\..8\..\..\..\..\..9" 1090 RETURN 9997 STOP 9998 SAVE "3D TIC-TAC" LINE 1 9999 CLS :PRINT AT 10,8;"REWIND TO VERIFY":PAUSE 200:VERIFY "3D TIC-TAC" ```