Classic Computer Magazine Archive COMPUTE! ISSUE 76 / SEPTEMBER 1986 / PAGE 84

3-D Tic-Tac-Toe for Atari ST

David Bohike

This new rendition of an old favorite lets you match wits against the ST computer in a three-dimensional contest. You can even, if you like, make changes to the program which will make the computer play more aggressively or more cautiously. "3-D Tic-Tac-Toe" runs on any Atari 520ST or 1040ST computer with a color monitor.

"3-D Tic-Tac-Toe" is a strategy game where you take on the Atari ST in a battle of wits. The object of the game is similar to the traditional Tic-Tac-Toe game, except this version takes place in a simulated three-dimensional space containing four game boards. To win, you must place four pieces in a row. The row may extend across a single plane or vertically though all four planes. Though it's not a flawless player, the ST will provide you with a formidable opponent.

Entering Tic-Tac-Toe

Type in the program as listed and save it to disk. The program works in either low- or medium-resolution modes. When you run the program, it randomly selects whether you or the computer should go first. The computer needs only a few seconds to pick its move and places a red uppercase C at the selected square. (The ST takes less time to move if you refrain from moving the mouse pointer around while it is calculating; moving the pointer freezes normal BASIC operations. In addition, you should avoid moving the slider bars on the output window, since this may jumble part of the game board.)

It's your turn when the screen prompt appears. Use the mouse to move to the square of your choice, then click the left mouse button. Due to the slowness of ST BASIC, you may need to hold the button down for as long as one second before the computer recognizes your choice. A blue uppercase H appears on the square you have chosen. The H, of course, stands for the Human, you, and the C stands for Computer.

Programmed Strategy

You may be interested in learning how the ST plays this simple strategy game. The computer does not use a "look-ahead" technique, but rather determines its move by assigning a numeric value to each empty square. This value is explained in the table, which shows a simple Tic-Tac-Toe combination of four squares in a row, along with the corresponding BASIC line number that assigns the value.

Combination Values

Line Pattern Value
540 HHHH human wins
540 CCCC computer wins
550 H_HH 33 points
560 _H_H 5 points
570 __H_ 2 points
580 CC_C 77 points
590 C__C 6 points
600 _C__ 1 point

Each computer piece is stored with a value of 5 in the V( ) array, and each human piece has a value of 1 in the array. So if a row of four squares contains two computer pieces, that combination has a value of 10. Lines 540-600 then convert these combination values into point values, which are evaluated to choose the next move. Note that the order of pieces in the table has no significance: What matters is the number of pieces and blanks. In the third entry, for instance, the sequence H_HH merely indicates that the row contains one blank and three human pieces, in any order. No value is assigned to a row that contains both computer pieces and human pieces since it's clearly impossible to win on that row.

This game is designed so that the computer plays a nearly equal balance of offense and defense. If you would like the computer to play more aggressively, increase the values for offensive moves in lines 590 and 600. For a more conservative game, you can increase the values in lines 560 and 570. With a little experience, you'll find that a change of just one or two points in these four lines will make a significant difference in the computer's move strategy.

3-D Tic-Tac-Toe

100 fullw 2: clearw 2
110 dim b(64),v(64),x(64),m(64,28):gosub 670
120 ' new game
130 clearw 2:color 1:print:for s=1 to 64:gosub 870
140 gotoxy x-1,y:print "\__\";:next
150 for i=1 to 64:b(i)=0:x(i)=0:v(i)=0:next:w(1)=0:mv=0
160 randomize 0:if rnd(1)<.5 then s=int(rnd(1)*64)+1:gosub 840:
    color 2:goto 370
170 ' human moves
180 gosub 840:color 4:print:gotoxy 0,0:print "Point and Click to MOVE"
190 gosub mousexy:mx=int(msx/9):my=int(msy/9.3)
200 sq=0:if msb<>1 then 190
210 for s=1 to 64:gosub 870
220 if y=my-2 and abs(x-mx)<=1 then sq=s
230 next:if sq=0 then 190
240 s=sq:gosub 870
250 if b(s)<>0 then 190
260 sx=1:gotoxy x,y:print "H_";:b(s)=1:v(s)=0:gosub 520
270 if w(1)>0 then 440
280 ' computer moves
290 gosub 840:color 2:print:gotoxy 0,0:print "Atari ST's Move        "
300 sx=0:for s=1 to 64:if b(s)>0 or x(s)=0 then 310 else v(s)=0:gosub 520
310 next
320 s=0:h=0:for i=1 to 64
330 if v(i)=h and rnd(1)<.3 and h>0 then h=v(i):s=i
340 if v(i)>h then h=v(i):s=i
350 next
360 if s=0 then gotoxy 0,0:print "    DRAW game       ";:
    a$="D":color 1:w(1)=1:w(2)=2:w(3)=3:w(4)=4:goto 460
370 gosub 870:b(s)=5:v(s)=0
380 for i=1 to 4:gotoxy x,y:print " *";:sound 1,8,1,4,10
390 gotoxy x,y:print "C_";:sound 1,8,1,5,10:next:sound 1,0,0,0,0
400 sx=1:for i=1 to 64:x(i)=0:next:gosub 520
410 if w(1)>0 then 450
420 goto 170
430 ' game over
440 gotoxy 0,0:print "You WIN                      ";:a$="H":goto 460
450 gotoxy 0,0:print "Computer WINS    ";:a$="C"
460 gotoxy 0,1:print "CLICK for new game";
470 for i=1 to 4:s=w(i):gosub 870:gotoxy x,y:print a$;:next:
    for i=1 to 99:next
480 sound 1,8,5,5,10:sound 1,0,0,0,0
490 for i=1 to 4:s=w(i):gosub 870:gotoxy x,y:print "  ";:next:
    for i=1 to 99:next
500 gosub mousexy:if msb<>0 then 120 else 470
510 ' adjust value array V(64) for computer move at square s
520 eg=0:j=1:for i=1 to m(s,0)
530 p=0:for k=1 to 4:p=p+b(m(s,j)):j=j+1:next:q=0
540 if p=4 or p=20 then for k=0 to 3:w(k+1)=m(s,j+k-4):next
550 if p=3 then q=33:goto 620
560 if p=2 then q=5:goto 620
570 if p=1 then q=2:goto 620
580 if p=15 then q=77:goto 620
590 if p=10 then q=6:goto 620
600 if p=5 then q=1:goto 620
610 if sx=1 then 620 else 660
620 v(s)=v(s)+q:if b(s)>0 then v(s)=0
630 if sx=0 then 660
640 for k=0 to 3:if b(m(s,j+k-4))=0 then x(m(s,j+k-4))=1
650 next
660 next:return
670 ' load legal win combos into m(64,28)
680 clearw 2:color 1:print "Loading DATA ..."
690 for i=1 to 64:m(i,0)=0:next
700 for i=1 to 16:a=i*4-3:for j=1 to 4:w(j)=a:a=a+1:next:gosub 820:next
710 for i=1 to 4:for j=i to i+48 step 16:n=j
720 for k=1 to 4:w(k)=n:n=n+4:next:gosub 820:next:next
730 for i=1 to 16:for j=0 to 3:w(j+1)=j*16+i:next:gosub 820:next
740 for i=1 to 28:for j=1 to 4:read a:w(j)=a:next:gosub 820:next:return
750 data 1,21,41,61,2,22,42,62,3,23,43,63,4,24,44,64
760 data 1,18,35,52,5,22,39,56,9,26,43,60,13,30,47,64
770 data 4,19,34,49,8,23,38,53,12,27,42,57,16,31,46,61
780 data 13,25,37,49,14,26,38,50,15,27,39,51,16,28,40,52
790 data 1,6,11,16,17,22,27,32,33,38,43,48,49,54,59,64
800 data 4,7,10,13,20,23,26,29,36,39,42,45,52,55,58,61
810 data 1,22,43,64,4,23,42,61,13,26,39,52,16,27,38,49
820 for k=1 to 4:l=m(w(k),0)*4+1:m(w(k),0)=m(w(k),0)+1
830 for p=1 to 4:m(w(k),l)=w(p):l=l+1:next:next:return
840 color 1:mv=mv+1:gosub clrprt:gotoxy 0,2:print "Move # ";mv;:return
850 clrprt:gotoxy 0,0:print spc(23);:return
860 ' input s=square to move to, returns x,y as print position
870 a=int((s-1)/16):y=a*4+3:b=s-a*16
880 c=int((b-1)/4):y=y+c-2:x=(4-a)*4+c
890 x=x+(b-c*4)*3-1:return
900 mousexy:poke contrl,124:poke contrl+2,0
910 poke contrl+6,0:vdisys(0)
920 msx=peek(ptsout):msy=peek(ptsout+2):msb=peek(intout):return