--- title: "Checkers" id: 71457 type: "computer_media" slug: "checkers-3" url: "http://localhost/computer_media/checkers-3/" markdown_url: "http://localhost/computer_media/checkers-3.md" published_at: "2026-09-09T08:57:35+00:00" modified_at: "2026-09-09T08:57:36+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/checkers.png" excerpt: "A fully playable checkers game with computer AI, custom piece graphics, king promotion, and a coordinate-based move input system packed into under 170 lines of BASIC." 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/" basic: - name: "User Defined Graphics (UDG)" slug: "user-defined-graphics-udg" taxonomy: "basic" url: "http://localhost/basic/user-defined-graphics-udg/" 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/Checkers%20(198x)(-)(TS2068)(US)(Program).zip" tsrun_member: "Checkers (198x)(-)(TS2068)(US)(Program).tap" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/09/checkers.png" media_type_tags: "Game" --- # Checkers Checkers implements a two-player checkers (draughts) game where one side is controlled by the computer, using a 45-element array to represent the 8×8 board with sentinel values. The board uses alphabetic column labels (A–H) combined with numeric row labels, encoded in a 32-entry lookup table loaded from DATA statements that maps position strings like “B1” to array indices. Computer AI searches for capture moves first, then falls back to randomized piece selection with a loop counter to avoid infinite searching. A custom UDG character is defined via POKE USR for the player’s pieces, while the computer’s pieces use the letter “O” and inverse video characters for kings. *** ### Program Structure The program is organized into several logical phases: 1. Lines 10–70: Title screen, initialization calls, and jump to setup 2. Lines 80–430: Main game loop — board display, player input, move validation, and turn switching 3. Lines 440–560: Board display subroutine, iterating array indices 40 down to 6 4. Lines 570–630: Piece rendering subroutine 5. Lines 640–1090: Computer AI — capture detection, double-jump attempts, random fallback 6. Lines 1100–1250: Forward-capture (king) logic for the computer 7. Lines 1300–1450: Board initialization and first-move prompt 8. Lines 1460–1510: Move-string decoder (converts e.g. “A3” to an array index) 9. Lines 1520–1580: Load coordinate lookup table from DATA 10. Lines 1590–1640: UDG definition for player piece graphic ### Board Representation The board is stored in a 45-element array `a()`. Indices 1–5 and 41–45 are sentinel cells set to 9. Indices 14, 23, and 32 are also set to 9, representing the unused square in each row of the staggered checkers grid. Valid playable squares use indices 6–40 (excluding the sentinels), and piece values are: | Value | Meaning | | --- | --- | | `NOT PI` (0) | Empty square | | `1` | Player’s man | | `2` | Player’s king | | `-1` | Computer’s man | | `-2` | Computer’s king | | `9` | Sentinel / off-board | Adjacent squares differ by 4 or 5 in index, and captures span 8 or 10. The staggered grid layout means rows alternate between 4- and 5-step offsets. ### Coordinate Lookup Table Lines 1520–1580 define a parallel pair of arrays: `m$(32,2)` holds 2-character position strings like `"A2"`, and `m(32)` holds the corresponding array index. The data is stored in a compact form in the DATA statements at lines 1530–1540, where each entry is a 5-character string such as `"B140"` — the first two characters are the label and the remaining characters are the index. Line 1570 uses `VAL c$(PI TO )` (i.e., `VAL c$(4 TO )`, since `PI` truncates to 3, so the slice starts at character 4) to extract the numeric index. The decoder subroutine at lines 1460–1510 performs a linear search through `m$()` to convert user input into an array index. ### Key BASIC Idioms - `NOT PI` evaluates to 0 (since `NOT` of any nonzero value is 0), used pervasively as a zero literal and to initialize variables like `p`, `q`, `si`, `sm`. - `VAL "number"` in `GO SUB` and slice operations is used as a memory-efficient literal. - `LET i= NOT PI: RETURN` at line 1500 signals a failed lookup to the caller, which checks `IF i= NOT PI` at lines 260 and 300 to re-prompt input. - The display subroutine iterates `FOR i=40 TO 6 STEP -1` so the board prints with the player’s side at the bottom. ### Computer AI The AI first scans all positions for backward captures (lines 660–690) and forward captures for kings (lines 700–720), jumping directly to specific move-execution blocks if found. If no capture is available, it falls back to a randomized loop (lines 750–880): a random starting index `z` is picked, legal moves are identified by setting `k` to 1, 2, or −7, and the loop retries up to 200 or 400 times before conceding. If the AI genuinely cannot move, it sets `sm=12` to signal a player win. Double-jump logic appears at lines 940–980 and 1040–1090, where after a capture the code checks if the landed piece can immediately capture again, executing a second jump in the same turn. However, this logic is partially inconsistent — variable `p` is used across multiple separate capture blocks without always being reset to 0, which can cause carry-over between turns. ### UDG and Graphics Lines 1590–1640 define a single UDG (character `\\a`) via `POKE USR "\\a"` with 8 bytes of circle/disc shape data from a DATA statement at line 1630. This UDG is used to render the player’s pieces. The computer’s men are displayed as `"O"`, kings use escape sequences with character codes 20 and 1/0 to achieve inverse video highlighting (lines 610–620). The board squares themselves are rendered using the block graphic `\\::` (a solid block █) in INK 2 (red). ### Notable Bugs and Anomalies - Line 1140 contains a double increment `z++3` (which BASIC parses as `z + +3`, equivalent to `z+3`), likely a typo for `z+13` or similar; this may cause incorrect double-jump detection. - Line 350 handles the case `c-b=8` (diagonal capture), clearing `a(c-5)`, but the symmetric case `c-b=10` clearing `a(c-4)` is absent — only the `b-c` directions are fully handled for the player’s captures. - Variable `p` (used for double-jump state) is initialized once at line 1410 but never reset between computer turns, meaning a double-jump flag from a previous turn could erroneously fire. - Line 730 contains `IF z <=40 THEN GO TO 730` as an increment-free loop, but the preceding `LET z=z+1` is a separate statement — this is an unusual but functional busy-wait scan pattern. - The move input at line 210 prompts for two values but uses a single `INPUT` with two string variables separated by a literal prompt string, which is valid BASIC syntax. ## Source Code ``` 10 PAPER 6:CLS 20 PRINT AT 6,13;"THIS "'' TAB 14;"IS"'' TAB 11;"CHECKERS" 30 BEEP .5,8:PAUSE 90:BEEP .5,12:CLS 40 REM CHECKERS 50 GO SUB 1590 60 GO SUB 1520 70 GO TO 1300 80 CLS 90 PRINT TAB 12; PAPER 1;"CHECKERS" 100 PRINT ,, 110 PRINT " "; PAPER 6;"ABCDEFGH" 120 GO SUB 440 130 PRINT "Your score ";sm,"Computers score ";si;" " 140 PRINT 150 IF u$="N" THEN GO TO 640 160 IF si=12 THEN PRINT "I Win ":STOP 170 IF sm=12 THEN PRINT "You win ":STOP 180 REM 190 IF q=2 THEN GO TO 400 200 PRINT "Last to ";f$; 210 INPUT "From (left,No. eg A3) ";c$;" to ";b$ 220 LET f$=b$ 230 LET d$=c$ 240 GO SUB 1460 250 LET c=m(i) 260 IF i= NOT PI THEN GO TO 210 270 LET d$=b$ 280 GO SUB 1460 290 LET b=m(i) 300 IF i= NOT PI THEN GO TO 210 310 IF ABS (c-b)=10 OR ABS (c-b)=8 THEN LET sm=sm+1 320 LET u$=" " 330 IF b-c=10 THEN LET a(b-5)= NOT PI 340 IF b-c=8 THEN LET a(b-4)= NOT PI 350 IF c-b=8 THEN LET a(c-5)= NOT PI 360 LET a(b)=a(c) 370 LET a(c)= NOT PI 380 LET q=2 390 GO TO 80 400 LET u$="":LET q= NOT PI 410 IF ABS (c-b)=10 OR ABS (c-b)=8 THEN PRINT ''':INPUT u$ 420 IF u$ <>"Y" THEN GO TO 640 430 GO TO 80 440 REM 450 LET m1= NOT PI:LET k=1 460 LET j=-1 470 FOR i=40 TO 6 STEP -1 480 IF a(i)=1 AND i>37 THEN LET a(i)=2 490 IF a(i)=-1 AND i<10 THEN LET a(i)=-2 500 IF i=14 OR i=32 OR i=23 THEN GO TO 560 510 IF m1= NOT PI THEN PRINT k;" ";:LET m1= NOT PI:LET k=k+1:LET j=-1*j:IF j=1 THEN PRINT INK 2;"\::"; 520 LET a=a(i) 530 GO SUB 570 540 IF m1 <>3 OR j=-1 THEN PRINT INK 2;"\::"; 550 LET m1=m1+1:IF m1>3 THEN LET m1= NOT PI:PRINT 560 NEXT i:PRINT :RETURN 570 REM print pieces 580 IF a= NOT PI THEN PRINT " "; 590 IF a=1 THEN PRINT "\a"; 600 IF a=-1 THEN PRINT "O"; 610 IF a=-2 THEN PRINT "\{20}\{1}O\{20}\{0}"; 620 IF a=2 THEN PRINT "\{20}\{1}\a\{20}\{0}"; 630 RETURN 640 LET u$=" ":LET q= NOT PI 650 LET z=6 660 IF z<9 THEN GO TO 700 670 IF a(z)<0 AND (a(z-4)=1 OR a(z-4)=2) AND a(z-8)= NOT PI THEN GO TO 890 680 IF z<11 THEN GO TO 700 690 IF a(z)<0 AND (a(z-5)=1 OR a(z-5)=2) AND a(z-10)= NOT PI THEN GO TO 990 700 IF z>25 THEN GO TO 730 710 IF a(z)=-2 AND (a(z+4)=1 OR a(z+4)=2) AND a(z+8)= NOT PI THEN GO TO 1100 720 IF a(z)=-2 AND (a(z+5)=1 OR a(z+5)=2) AND a(z+10)= NOT PI THEN GO TO 1210 730 LET z=z+1:IF z <=40 THEN GO TO 730 740 REM RANDOMIZE 750 LET u= NOT PI 760 LET z=6+ INT (RND*34)+1 770 LET k= NOT PI 780 LET u=u+1 790 IF a(z)<0 AND a(z-4)= NOT PI THEN LET k=1 800 IF a(z)<0 AND a(z-5)= NOT PI AND k= NOT PI THEN LET k=2 810 IF k= NOT PI AND z<26 AND a(z)=-2 AND a(z+4)= NOT PI THEN LET k=-7 820 IF z<10 THEN GO TO 840 830 IF (k=1 OR k=2) AND u<200 AND (a(z-(10 AND z>10))=1 OR a(z-8)=1) THEN GO TO 760 840 IF k= NOT PI AND u<400 THEN GO TO 760 850 IF k= NOT PI THEN LET sm=12:GO TO 80 860 LET a(z-(3+k))=a(z) 870 LET a(z)= NOT PI 880 GO TO 80 890 LET a(z-8)=a(z) 900 LET a(z)= NOT PI 910 LET a(z-4)= NOT PI 920 LET si=si+1 930 IF z<24 THEN GO TO 80 940 IF (a(z-13)=1 OR a(z-13)=2) AND a(z-18)= NOT PI THEN LET p=2 950 IF p=1 THEN LET a(z-18)=a(z-8):LET a(z-13)= NOT PI 960 IF p=2 THEN LET a(z-8)= NOT PI 970 IF p>0 THEN LET a(z-8)= NOT PI 980 GO TO 80 990 LET a(z-10)=a(z) 1000 LET a(z)= NOT PI 1010 LET a(z-5)= NOT PI 1020 LET si=si+1 1030 IF z<25 THEN GO TO 80 1040 IF (a(z-15)=1 OR a(z-15)=2) AND a(z-20)= NOT PI THEN LET p=1 1050 IF (a(z-14)=1 OR a(z-14)=2) AND a(z-18) THEN LET p=2 1060 IF p=1 THEN LET a(z-15)= NOT PI:LET a(z-20)=a(z-10) 1070 IF p=2 THEN LET a(z-14)= NOT PI:LET a(z-18)=a(z-10) 1080 IF p>0 THEN LET a(z-10)= NOT PI 1090 GO TO 80 1100 LET a(z+8)=-2 1110 LET a(z+4)= NOT PI 1120 LET a(z)= NOT PI 1130 LET si=si+1 1140 IF z<32 AND (a(z++3)=1 OR a(z+3)=2) AND a(z-2)= NOT PI THEN LET p=1 1150 IF z<23 AND (a(z+14)=1 OR a(z+14)=2) AND a(z+16)=2 THEN LET p=2 1160 IF z<23 AND (a(z+13)=1 OR a(z+13)=2) AND a(z+18)= NOT PI THEN LET p=3 1170 IF p=1 THEN LET a(z+3)= NOT PI:LET a(z-2)=-2 1180 IF p=2 THEN LET a(z+14)= NOT PI:LET a(z+16)= NOT PI 1190 IF p=3 THEN LET a(z+13)= NOT PI:LET a(z+18)=-2 1200 IF p>0 THEN LET a(z+8)= NOT PI 1210 LET a(z+10)=-2 1220 LET a(z+5)= NOT PI 1230 LET a(z)= NOT PI 1240 LET si=si+1 1250 GO TO 80 1260 PRINT :PRINT 1270 PRINT :PRINT 1280 RETURN 1290 REM * initialize * 1300 DIM a(45) 1310 PRINT 1320 FOR z=1 TO 45 1330 IF z<6 THEN LET a(z)=9 1340 IF z>5 AND z<19 THEN LET a(z)=1 1350 IF z>18 AND z<28 THEN LET a(z)= NOT PI 1360 IF z>27 AND z<41 THEN LET a(z)=-1 1370 IF z>40 THEN LET a(z)=9 1380 NEXT z 1390 LET a(14)=9:LET a(23)=9:LET a(32)=9 1400 LET f$="--":LET u$="" 1410 LET p= NOT PI:LET q=p:LET si=p:LET sm=p 1420 INPUT "Do You Want The First Move Y/N"; LINE q$ 1430 PRINT 1440 IF q$ <>"Y" THEN GO TO 640 1450 GO TO 80 1460 REM decodeMOVE 1470 LET i=1 1480 IF m$(i)=d$ THEN RETURN 1490 LET i=i+1 1500 IF i=33 THEN LET i= NOT PI:RETURN 1510 GO TO 1480 1520 DIM m$(32,2):DIM m(32) 1530 DATA "B140","D139","F138","H137","A236","C235","E234","G233","B331","D330","F329","H328","A427","C426","E425","G424","B522","D521","F520","H519","A618","C617","E616" 1540 DATA "G615","B713","D712","F711","H710","A809","C808","E807","G806" 1550 RESTORE 1530 1560 FOR i=1 TO 32 1570 READ c$:LET m$(i)=c$:LET m(i)= VAL c$(PI TO ) 1580 NEXT i:RETURN 1590 BORDER NOT PI:PAPER NOT PI:INK 9:CLS 1600 RESTORE 1630:FOR a= NOT PI TO 7 1610 READ u:POKE USR "\a"+a,u 1620 NEXT a:RETURN 1630 DATA 0,60,126,u,u,u,60,0 1640 REM a=\a ```