3-D Tic-Tac-Toe for Atari ST
David BohikeThis 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