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:
- Lines 10–70: Title screen, initialization calls, and jump to setup
- Lines 80–430: Main game loop — board display, player input, move validation, and turn switching
- Lines 440–560: Board display subroutine, iterating array indices 40 down to 6
- Lines 570–630: Piece rendering subroutine
- Lines 640–1090: Computer AI — capture detection, double-jump attempts, random fallback
- Lines 1100–1250: Forward-capture (king) logic for the computer
- Lines 1300–1450: Board initialization and first-move prompt
- Lines 1460–1510: Move-string decoder (converts e.g. “A3” to an array index)
- Lines 1520–1580: Load coordinate lookup table from DATA
- 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 PIevaluates to 0 (sinceNOTof any nonzero value is 0), used pervasively as a zero literal and to initialize variables likep,q,si,sm.VAL "number"inGO SUBand slice operations is used as a memory-efficient literal.LET i= NOT PI: RETURNat line 1500 signals a failed lookup to the caller, which checksIF i= NOT PIat lines 260 and 300 to re-prompt input.- The display subroutine iterates
FOR i=40 TO 6 STEP -1so 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 asz + +3, equivalent toz+3), likely a typo forz+13or similar; this may cause incorrect double-jump detection. - Line 350 handles the case
c-b=8(diagonal capture), clearinga(c-5), but the symmetric casec-b=10clearinga(c-4)is absent — only theb-cdirections 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 730as an increment-free loop, but the precedingLET z=z+1is 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
INPUTwith 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
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
