Checkers

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Game

This program implements a two-player checkers (draughts) game where a human plays against a computer opponent on an 8×8 board. The board state is stored in a one-dimensional array Q(99), where piece positions are encoded using ASCII character codes: H for human checkers, K for human kings, C for computer checkers, and $ for computer kings. The computer’s move selection uses a scored candidate list S(10) combined with RND-based random selection, and falls back to random wandering if no strategic moves are found within 300 attempts. King promotion is handled by scanning rows 11–18 for computer pieces and rows 82–88 for human pieces after each move. The title screen uses OVER 1 and block graphic characters (█) to draw a checkerboard pattern, with FLASH and INVERSE attributes applied to a scrolling “CHECKERS ANYONE?” display.

Program Structure

The program is organized into several logical sections accessed via GO SUB:

  • Lines 1–3: Title/splash screen with scrolling CHECKERS text using inverse characters and BEEP.
  • Lines 10–110: Main game loop. POKE 23658,8 enables caps-lock mode. The flow calls initialization (GO SUB 1010), then alternates between the computer move routine (GO SUB 600, GO SUB 130) and the human move routine (GO SUB 760).
  • Lines 130–580: Computer AI — candidate move scoring, jump detection, and piece movement.
  • Lines 600–750: Board display and win detection.
  • Lines 760–990: Human input handler, move validation, jump logic, and king promotion.
  • Lines 1010–1260: Initialization — array setup, board population from DATA statements, direction vectors.
  • Lines 1270–1330: Special-case logic forcing the computer to advance a piece to the king row.
  • Lines 1340–9998: Utility routines — delay loop, decorative checkerboard overlay, and animated title card.

Board Representation

The board is a flat array Q(99) indexed by a two-digit row-column scheme (e.g., position 34 = row 3, column 4). Squares are initialized to OF=-99 as an off-board sentinel. Valid squares are seeded from 64 DATA pairs (position, piece-code). The piece encoding uses ASCII codes directly:

VariableASCII charMeaning
HH (72)Human checker
HKK (75)Human king
CC (67)Computer checker
CK$ (36)Computer king
Espace (32)Empty square

This allows the board to be printed directly using CHR$ (Q(F+G)) at line 660 without any translation table — an efficient trick that blends storage and display.

Direction Vectors

Movement directions are stored in N(4), loaded from DATA -11,-9,11,9. Indices 1–2 represent forward (toward lower row numbers, i.e., the computer’s advancing direction) and indices 3–4 represent backward. A regular checker uses B up to 2; a king uses B up to 4. This is checked with the guard IF B<2 OR (Q(A)=CK AND B<4) at lines 230 and 380.

Computer AI

The computer’s move generation (lines 130–580) scans all positions from 89 down to 11. For each computer piece found, it evaluates up to 4 directions. Capture moves (jump over an adjacent human piece into an empty landing square) are executed immediately at line 280. Non-capture moves are scored and stored in S(SC) as 100*A + B + 20, encoding both the source square and direction index into a single integer. A random candidate is then selected from the list.

If no scored moves exist (SC=0), the computer falls back to random piece selection (lines 470–550), retrying up to 300 times before conceding at line 560. This is a simple but functional fallback that prevents lockup in sparse board positions.

The subroutine at lines 1270–1330 provides a special override: if a computer piece is on row 2 (positions 21–28) and the corresponding king-row square is empty, it forces that advancing move and sets flag FL=1 to bypass the normal move selection.

Human Input and Validation

The human enters moves as two separate INPUT values: the source position A and destination B, each as a two-digit row-column number. Entry of 99 at the “FROM” prompt concedes the game. Validation checks that the source contains a human piece (H or HK) and the destination is empty. Jumps are detected by ABS(A-B)>=12 at line 900 — if the move spans more than one row step, it is treated as a capture and the intermediate square is cleared at line 940. The player is then asked if they wish to jump again, supporting multi-jump turns.

King Promotion

After the human moves, lines 850–880 scan rows 11–17 (positions 11–18) for computer pieces that have reached the human’s back rank and promote them to CK, and rows 82–88 for human pieces to promote to HK. The same scan is repeated at lines 950–960 after a capture, ensuring promotion happens correctly mid-multi-jump. Note that line 855 contains LET CH= CODE "$", which assigns a value to CH but this variable is never subsequently used — it appears to be an unused remnant.

Display Routine

The board is rendered at lines 600–680 by printing the column header, then iterating F from 80 to 10 in steps of -10 (rows 8 down to 1), printing CHR$ (Q(F+G)) for each column G from 1 to 8. Win detection at line 690 checks if either capture count (CO for computer, HU for human) has reached 12.

Title Screen Animation

Lines 1564–1700 draw a decorative checkerboard using PRINT OVER 1 with solid block graphic characters (█) across multiple rows, then display “CHECKERS ANYONE?” one character at a time with FLASH 1 and INVERSE 1 active, producing a flashing inverse-video crawl effect.

Notable Anomalies

  • Line 310 references LET A=M+N where N is the scalar initialized at line 1010 as 0, not the array N(). This means after a computer jump, the re-jump scan starts from the original landing square offset by 0, which is likely a bug where N(B) was intended.
  • The condition at line 220 is extremely long and complex, combining multiple strategic heuristics (avoiding squares attacked by human pieces, preferring safe destinations) in a single IF chain. It is difficult to verify correctness and likely contains logical oversights.
  • Line 855 sets CH= CODE "$" inside the king-promotion loop but CH is never read elsewhere in the program.
  • The DIM S(10) at line 1060 limits the scored move list to 10 entries, but the guard at line 400 is IF SC<10, so only indices 1–10 are used safely.

Image Gallery

Source Code

    1 :BRIGHT 1:BORDER 2:INK 0:PAPER 2:BEEP 1,9:CLS :FOR C=1 TO 44:PRINT "CHECKERS\{20}\{1}CHECKERS\{20}\{0}";:NEXT C
    3 PAUSE 90:BEEP 1,6:CLS 
   10 POKE 23658,8
   20 GO SUB 1010
   30 PAUSE 90:CLS 
   50 GO TO 90
   75 GO SUB 600
   80 GO SUB 760
   90 GO SUB 600
  100 GO SUB 130
  110 GO TO 70
  130 FOR X=1 TO 10:LET S(X)=1:NEXT X
  140 LET SC=0:LET A=89
  150 LET A=A-1
  160 IF Q(A) <>C AND Q(A) <>CK THEN GO TO 240
  170 LET B=0:IF A<29 THEN LET B=2
  180 LET B=B+1
  190 LET M=A+N(B)
  200 IF M>88 OR M<11 THEN GO TO 240
  210 IF (Q(M)=H OR Q(M)=HK) AND Q(M+N(B))=E THEN GO TO 280
  220 IF Q(M)=E THEN IF (Q(M-11) <>H AND Q(M-11) <>HK) THEN IF (Q(M-9) <>H AND Q(M-9) <>HK) AND Q(M+9) <>HK THEN IF Q(M+8) <>HK AND (Q(M+9) <>C OR Q(M+9) <>CK OR Q(M+10)=C OR Q(M+11)=CK AND Q(M+11) <>HK) THEN GO SUB 400
  230 IF B<2 OR (Q(A)=CK AND B<4) THEN GO TO 180
  240 IF A>11 THEN GO TO 150
  250 LET FL=0:IF Q(22)=C OR Q(24)=C OR Q(26)=C OR Q(28)=C THEN GO SUB 1270
  260 IF FL=1 THEN GO TO 570
  270 GO TO 420
  280 LET Q(M+N(B))=Q(A):LET Q(M)=E:LET Q(A)=E
  290 LET CO=CO+1
  300 GO SUB 600
  310 LET A=M+N
  320 LET B=0
  330 LET B=B+1
  340 IF (A+2*N(B)<11 OR A+2*N(B)>88) AND B<4 THEN GO TO 330
  350 LET M=A+N(B)
  360 IF Q(M)=C AND B>3 THEN RETURN 
  370 IF (Q(M)=H OR Q(M)=HK) AND Q(M+N(B))=E THEN GO TO 280
  380 IF B<2 OR (Q(A)=CK AND B<4) THEN GO TO 230
  390 RETURN 
  400 IF SC<10 THEN LET SC=SC+1
  410 LET S(SC)=100*A+B+20:RETURN 
  420 IF SC=0 THEN GO TO 470
  430 LET XC= INT (RND*SC)+1
  440 LET A= INT (S(XC)/100)
  450 LET M=A+N(S(XC)-100*A-20)
  460 GO TO 570
  470 LET SC=SC+1:LET A= INT (RND*88)+1
  480 IF Q(A) <>C AND Q(A) <>CK THEN GO TO 550
  490 LET B=0
  500 LET B=B+1
  510 LET M=A+N(B)
  520 IF M>88 OR M<11 THEN GO TO 540
  530 IF Q(M)=E THEN GO TO 570
  540 IF B<2 OR Q(A)=CK AND B<4 THEN GO TO 500
  550 IF SC<300 THEN GO TO 470
  560 PRINT AT 19,0;"I CONCEDE THE GAME  "
  565 STOP 
  570 LET Q(M)=Q(A):LET Q(A)=E
  580 RETURN 
  600 PRINT AT 0,0;"                               ":PRINT "                               ":PRINT "                               "
  610 PRINT "    COMPUTERS---C         "
  620 PRINT "     HUMAN   ---H"
  630 PRINT "  1 2 3 4 5 6 7 8"
  640 FOR F=80 TO 10 STEP -10
  650 PRINT F/10;" ";
  660 FOR G=1 TO 8:PRINT CHR$ (Q(F+G));" ";:NEXT G
  670 PRINT F/10:NEXT F
  680 PRINT "  1 2 3 4 5 6 7 8"
  690 IF CO=12 OR HU=12 THEN GO TO 710
  695 GO SUB 1560
  700 RETURN 
  710 IF HU=12 THEN PRINT AT 19,0;"YOU HAVE WON "
  720 IF CO=12 THEN PRINT AT 19,0;"I'VE WON "
  730 PRINT '"THANKS FOR THE GAME "
  740 STOP 
  750 REM 99 TO CONCEDE
  760 PRINT 
  770 PRINT AT 17,3;"ENTER YOUR MOVE"
  780 INPUT "FROM ";A
  790 IF A=99 THEN GO TO 730
  800 IF Q(A) <>H AND Q(A) <>HK THEN GO TO 780
  810 INPUT "TO ";B
  820 IF Q(B) <>E THEN GO TO 810
  830 LET Q(B)=Q(A):LET Q(A)=E
  850 FOR T=11 TO 17:IF Q(T)=C THEN LET Q(T)=CK
  855 LET CH= CODE "$"
  860 NEXT T
  870 FOR T=82 TO 88:IF Q(T)=H THEN LET Q(T)=HK
  880 NEXT T
  900 IF ABS (A-B)<12 THEN RETURN 
  910 LET TY= RND
  920 IF TY<.3 THEN PRINT AT 19,0;"GOOD MOVE  ":GO SUB 1340
  930 IF TY>.7 THEN PRINT AT 19,0;"GOT ME!!  ":GO SUB 1340
  940 LET HU=HU+1:LET Q((A+B)/2)=E:GO SUB 600
  950 FOR T=82 TO 88:IF Q(T)=H THEN LET Q(T)=HK
  960 NEXT T
  970 PRINT :INPUT "CAN YOU JUMP AGAIN (Y OR N)";A$
  980 IF A$ <>"Y" AND A$ <>"y" THEN RETURN 
  990 LET A=B:GO TO 800
 1010 LET N=0:REM INITIALIZE
 1040 CLS :BORDER 0
 1042 PRINT "ENTER MOVES AS ROW-COLUMN PAIRS---EXAMPLE:  TO MOVE THE PIECE   MARKED H (HUMAN'S CHECKER) AT   THE LEFT OF THE BOARD, ENTER 31--NO COMMA, NO HYPHEN."
 1045 PRINT ''"COMPUTER ALWAYS TAKES 1ST MOVE."
 1050 LET N=N+1
 1060 DIM Q(99):DIM N(4):DIM S(10)
 1070 LET H= CODE ("H"):LET HK= CODE ("K") 
 1080 LET C= CODE ("C") :LET CK= CODE ("$")
 1090 LET E=32:LET OF=-99
 1100 FOR M=1 TO 99:LET Q(M)=OF:NEXT M
 1110 FOR M=1 TO 64
 1120 READ D:READ G
 1130 LET Q(D)=G:NEXT M
 1136 DATA 81,32,82,67,83,32,84,67,85,32,86,67,87,32
 1150 DATA 88,67,71,67,72,32,73,67,74,32,75,67,76,32
 1160 DATA 77,67,78,32,61,32,62,67,63,32,64,67
 1170  DATA 65,32,66,67,67,32,68,67,51,32,52,32
 1180 DATA 53,32,54,32,55,32,56,32,57,32,58,32
 1190 DATA 41,32,42,32,43,32,44,32,45,32,46,32
 1200 DATA 47,32,48,32,31,72,32,32,33,72,34,32,\{20}\{1}\{20}\{1}\{20}\{0}35,72
 1210 DATA 36,32,37,72,38,32,21,32,22,72,23,32,24,72
 1220 DATA 25,32,26,72,27,32,28,72,11,72,12,32,13,72
 1230 DATA 14,32,15,72,16,32,17,72,18,32
 1240 FOR M=1 TO 4:READ X:LET N(M)=X:NEXT M
 1250 DATA -11,-9,11,9
 1260 LET CO=0:LET HU=0:RETURN 
 1270 IF Q(22)=C AND Q(11)=E THEN LET A=22:LET M=11:LET FL=1:RETURN 
 1280 IF Q(22)=C AND Q(13)=E THEN LET A=22:LET M=13:LET FL=1:RETURN 
 1290 IF Q(24)=C AND Q(13)=E THEN LET A=24:LET M=13:LET FL=1:RETURN 
 1300 IF Q(24)=C AND Q(15)=E THEN LET A=24:LET M=15:LET FL=1:RETURN 
 1310 IF Q(26)=C AND Q(15)=E THEN LET A=26:LET M=15:LET FL=1:RETURN 
 1320 IF Q(26)=C AND Q(17)=E THEN LET A=26:LET M=17:LET FL=1:RETURN 
 1330 RETURN 
 1340 FOR O=1 TO 300:NEXT O:PRINT AT 18,0; AT 14,0;"                                ":RETURN 
 1564 PRINT OVER 1; AT 6,2;"\::\::  \::\::  \::\::  \::\::  ":PRINT OVER 1; AT 7,2;"  \::\::  \::\::  \::\::  \::\::";:PRINT OVER 1, AT 8,2;"\::\::  \::\::  \::\::  \::\:: "
 1566 PRINT OVER 1; AT 9,2;"  \::\::  \::\::  \::\::  \::\::":PRINT OVER 1, AT 10,2;"\::\::  \::\::  \::\::  \::\::  "
 1568 PRINT OVER 1, AT 11,2;"  \::\::  \::\::  \::\::  \::\::":PRINT OVER 1, AT 12,2;"\::\::  \::\::  \::\::  \::\::  "
 1570 PRINT OVER 1, AT 13,2;"  \::\::  \::\::  \::\::  \::\::"
 1600 FLASH 1:INVERSE 1:LET A=28:LET B=2:LET C$="CHECKERS ANYONE?":FOR D=1 TO 16:LET B=B+1:PRINT AT B,A;C$(D):NEXT D
 1700 PAUSE 30:FLASH 0:INVERSE 0
 9990 RETURN 
 9995 STOP 
 9997 REM CLEAR :RANDOMIZE USR 100:SAVE "CHEKRS.B1"
 9998 REM CLEAR :RANDOMIZE USR 100:LOAD "L.B1"

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.