home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / euphoria / ttt.ex < prev    next >
Text File  |  1994-01-31  |  19KB  |  899 lines

  1.         -------------------------------
  2.         -- 3-Dimensional Tic Tac Toe --
  3.         -------------------------------
  4.  
  5. -- Play 3 dimensional tic-tac-toe against one of two computer algorithms
  6. -- or against another human -- or let the two computer algorithms play
  7. -- each other. Which algorithm is better?
  8.  
  9. -- There are two major data structures. positions describes each board 
  10. -- position. lines describes each possible winning line of 4 positions  
  11. -- in a row.
  12.  
  13. include graphics.e
  14. include mouse.e
  15.  
  16. constant TRUE = 1, FALSE = 0
  17. constant ON = 1, OFF = 0
  18.  
  19. constant GRAY = 8,
  20.      BRIGHT_GREEN = 10,
  21.      BRIGHT_RED = 12,
  22.      BRIGHT_MAGENTA= 13, 
  23.      BRIGHT_YELLOW = 14, 
  24.      BRIGHT_BLUE = 9, 
  25.      BRIGHT_WHITE = 15
  26.  
  27. constant COLORS = {BRIGHT_RED, BRIGHT_GREEN, BRIGHT_YELLOW, BRIGHT_MAGENTA}
  28.  
  29. sequence pcolors -- colors of circular markers
  30. pcolors = {BRIGHT_BLUE, BRIGHT_WHITE}
  31.  
  32. constant SQUARE_SIZE = 24
  33.  
  34. constant TOP_LEFT = {240, 26}
  35.  
  36. constant KEYB = 0, SCREEN = 1  -- I/O devices
  37.  
  38. constant
  39.     NPOSITIONS = 64,  -- number of board positions
  40.     NLINES = 76   -- number of 4-in-a-row lines
  41.  
  42. type line(integer x)
  43.     return x >= 0 and x <= NLINES
  44. end type
  45.  
  46. type Position(integer x)
  47.     return x >= 0 or x <= NPOSITIONS
  48. end type
  49.  
  50. type all_positions(sequence x)
  51.     return length(x) = NPOSITIONS
  52. end type
  53.  
  54. type all_lines(sequence x)
  55.     return length(x) = NLINES
  56. end type
  57.  
  58. type boolean(integer x)
  59.     return x = TRUE or x = FALSE
  60. end type
  61.  
  62. type players(sequence x)
  63.     return length(x) = 4
  64. end type
  65.  
  66. type player_number(integer x)
  67.     return x = 1 or x = 2
  68. end type
  69.  
  70. type positive_int(integer x)
  71.     return x >= 1
  72. end type
  73.  
  74. type natural(integer x)
  75.     return x >= 0
  76. end type
  77.  
  78. type human_count(integer x)
  79.     return x >=0 and x <= 2
  80. end type
  81.  
  82. type move_value(integer x)
  83.     return integer(x) and x >= -1
  84. end type
  85.  
  86. type time_delay(integer x)
  87.     return x >= 0 and x < 1000
  88. end type
  89.  
  90. type reason_number(integer x)
  91.     return x >= 1 and x <= 10
  92. end type
  93.  
  94. type three_digits(sequence x)
  95.     return length(x) = 3
  96. end type
  97.  
  98. type move_number(integer x)
  99.     return x >= 111 and x <= 444
  100. end type
  101.  
  102. all_positions positions
  103.     -- positions is a list of all the board positions
  104.  
  105. constant
  106.     -- positions 2-d sequence columns:
  107.     LINES_THRU = 1, -- the number of lines passing through this position
  108.     LINE1 = 2,      -- the first of up to 7 lines passing
  109.             -- through this position
  110.     NLIVE = 9,      -- the number of "live" lines passing through this position
  111.     NEXTP = 10,     -- index of next position (or 0)
  112.     PREVP = 11,     -- index of previous position (or 0)
  113.     AVAIL = 12      -- is this position available, 1 = yes, 0 = no
  114.  
  115. all_lines lines     -- lines is a list of all the lines of 4 positions in a row
  116.                 -- it is indexed from 1 to NLINES
  117.  
  118. constant
  119.     -- lines 2-d sequence columns:
  120.     COUNT = 1,   -- number of "live" markers on this line
  121.     POS1 = 2,    -- first position of 4
  122.     POS4 = 5,    -- last position
  123.     NEXTL = 6,   -- index of next line (or 0)
  124.     PREVL = 7,   -- index of previous line (or 0)
  125.     STATUS = 8,  -- status of this line
  126.         -- possible status of a line:
  127.         EMPTY = 0,
  128.         COMPUTER = 1,
  129.         HUMAN = 2,
  130.         DEAD = 3
  131.  
  132. sequence lp       -- L->P format
  133. all_positions pl  -- P->L format
  134. sequence dbl      -- used in 3x3 check
  135. players ptype,    -- player types
  136.         pname     -- player names
  137.  
  138. line fptr,  -- free position list
  139.      cptr,  -- computer's line list
  140.      hptr,  -- human's line list
  141.      eptr   -- empty line list
  142. player_number player
  143. natural cmoves, hmoves, l2
  144. boolean endgame, found
  145. human_count humans
  146. move_value bestval
  147. atom x
  148.  
  149. procedure Delay(time_delay t)
  150. -- waste some time
  151.     atom t0
  152.  
  153.     if humans = 0 and endgame = FALSE then
  154.     return
  155.     end if
  156.     t0 = time()
  157.     while time() < t0 + t/700 do
  158.     end while
  159. end procedure
  160.  
  161. procedure Why(reason_number reason)
  162. -- show the reason why the computer made its move
  163.     position(22, 11)
  164.     if reason = 1 then
  165.     puts(SCREEN, "BLOCK 3 IN A ROW")
  166.     elsif reason = 2 then
  167.     puts(SCREEN, "FORCE 3X3       ")
  168.     elsif reason = 3 then
  169.     puts(SCREEN, "FORCE 3-2-2-1   ")
  170.     elsif reason = 4 then
  171.     puts(SCREEN, "FORCE 3-2-2     ")
  172.     elsif reason = 5 then
  173.     puts(SCREEN, "PREVENT 3X3     ")
  174.     elsif reason = 6 then
  175.     puts(SCREEN, "PREVENT 3-2-2-1 ")
  176.     elsif reason = 7 then
  177.     puts(SCREEN, "PREVENT 3-2-2   ")
  178.     elsif reason = 8 then
  179.     printf(SCREEN, "VALUE=%d         ", bestval)
  180.     else
  181.     puts(SCREEN, "                ")
  182.     end if
  183. end procedure
  184.  
  185.  
  186. function Get4th()
  187. -- grab the final winning 4th position in a line
  188. integer pos
  189.     for z = POS1 to POS4 do
  190.     pos = lines[x][z]
  191.     if positions[lp[pos]][AVAIL] = 0 then
  192.         return pos
  193.     end if
  194.     end for
  195. end function
  196.  
  197.  
  198. function Find2()
  199. -- Find two lines that intersect where I have 2 markers on each line.
  200. -- I can take the intersection and create two lines of 3 at once.
  201. integer pos
  202.     for z = POS1 to POS4 do
  203.     pos = lines[x][z]
  204.     if positions[lp[pos]][AVAIL] = 0 then
  205.         dbl[l2] = pos
  206.         l2 = l2 + 1
  207.     end if
  208.     end for
  209.     if l2 < 4 then
  210.     return 0
  211.     end if
  212.     for z = l2 - 2 to l2 - 1 do
  213.     for z1 = 1 to l2 - 3 do
  214.         if dbl[z] = dbl[z1] then
  215.         found = TRUE
  216.         return dbl[z]
  217.         end if
  218.     end for
  219.     end for
  220.     return 0
  221. end function
  222.  
  223.  
  224. function FindA()
  225. -- find forcing pattern "A"
  226. integer k, z1, line, zz
  227.     k = 0
  228.     for z = POS1 to POS4 do
  229.     z1 = lp[lines[x][z]]
  230.     for i = LINE1 to positions[z1][LINES_THRU] + 1 do
  231.         line = positions[z1][i]
  232.         if lines[line][STATUS] = l2 then
  233.         if lines[line][COUNT] = 2 then
  234.             k = k + 1
  235.             exit
  236.         end if
  237.         end if
  238.     end for
  239.     if k = 3 then
  240.         zz = z
  241.         exit
  242.     end if
  243.     end for
  244.     if k = 3 then
  245.     found = TRUE
  246.     return lines[x][zz]
  247.     end if
  248.     return 0
  249. end function
  250.  
  251.  
  252. function FindB()
  253. -- find forcing pattern "B"
  254. integer k, z1, line
  255.     k = 0
  256.     for z = POS1 to POS4 do
  257.     z1 = lp[lines[x][z]]
  258.     if positions[z1][AVAIL] = 0 then
  259.         for i = LINE1 to positions[z1][LINES_THRU] + 1 do
  260.         line = positions[z1][i]
  261.         if lines[line][STATUS] = l2 then
  262.             if lines[line][COUNT] = 2 then
  263.             k = k + 1
  264.             exit
  265.             end if
  266.         end if
  267.         end for
  268.         if k = 2 then
  269.         found = TRUE
  270.         return lines[x][z]
  271.         end if
  272.     end if
  273.     end for
  274.     return 0
  275. end function
  276.  
  277.  
  278. function FindMax()
  279. -- find best free position
  280. integer i, bestm
  281.     i = fptr
  282.     bestval = -1
  283.     while i do
  284.     if positions[i][NLIVE] > bestval then
  285.         bestval = positions[i][NLIVE]
  286.         bestm = i
  287.     elsif positions[i][NLIVE] = bestval then
  288.         if rand(7) = 1 then
  289.         bestm = i
  290.         end if
  291.     end if
  292.     i = positions[i][NEXTP]
  293.     end while
  294.     return pl[bestm]
  295. end function
  296.  
  297. function mouse_square(sequence spot)
  298. -- map x,y mouse coordinate to plane, row, column
  299.     integer x, y
  300.     natural m
  301.  
  302.     spot = spot - TOP_LEFT
  303.     x = spot[1]
  304.     y = spot[2]
  305.     -- which plane are we on?
  306.     m = 111
  307.     while y > 4 * SQUARE_SIZE do
  308.     y = y - 4.5 * SQUARE_SIZE
  309.     x = x - 2.5 * SQUARE_SIZE
  310.     m = m + 100
  311.     end while
  312.     -- which row are we on?
  313.     while y > SQUARE_SIZE do
  314.     y = y - SQUARE_SIZE
  315.     m = m + 10
  316.     end while
  317.     if x > 4 * SQUARE_SIZE then
  318.     return 0 
  319.     end if
  320.     -- which column are we on?
  321.     while x > SQUARE_SIZE do
  322.     x = x - SQUARE_SIZE
  323.     m = m + 1
  324.     end while
  325.     if x < 0 or y < 0 then
  326.     return 0
  327.     else
  328.     return m
  329.     end if
  330. end function
  331.  
  332.  
  333. function GetMove()
  334. -- get human's move via the mouse
  335.     natural m
  336.     object event
  337.  
  338.     while TRUE do
  339.     position(20, 1)
  340.     puts(SCREEN, repeat(' ', 30))
  341.     position(20, 1)
  342.     puts(SCREEN, ' ' & pname[player])
  343.     puts(SCREEN, "'s move? ")
  344.     event = -1
  345.     while atom(event) do
  346.         event = get_mouse()
  347.     end while
  348.     m = mouse_square(event[2..3])
  349.     if m >= 111 and m <= 444 then
  350.         if lp[m] then
  351.         if positions[lp[m]][AVAIL] = 0 then
  352.             puts(SCREEN, repeat(' ', 30))
  353.             exit
  354.         end if
  355.         end if
  356.     end if
  357.     end while
  358.     return m
  359. end function
  360.  
  361.  
  362. procedure AdjValues(integer x, integer delta)
  363. -- adjust the "value" of positions along a line
  364. integer pos
  365.     for z = POS1 to POS4 do
  366.     pos = lp[lines[x][z]]
  367.     positions[pos][NLIVE] = positions[pos][NLIVE] + delta
  368.     end for
  369. end procedure
  370.  
  371.  
  372. procedure Relink(integer player, integer x)
  373. -- adjust some data structures after a move
  374.     line prev, next
  375.  
  376.     next = lines[x][NEXTL]
  377.     prev = lines[x][PREVL]
  378.  
  379.     if player = COMPUTER then
  380.     AdjValues(x, 1)
  381.     lines[x][NEXTL] = cptr
  382.     lines[x][PREVL] = 0
  383.     if cptr then
  384.         lines[cptr][PREVL] = x
  385.     end if
  386.     cptr = x
  387.     else
  388.     lines[x][NEXTL] = hptr
  389.     lines[x][PREVL] = 0
  390.     if hptr then
  391.         lines[hptr][PREVL] = x
  392.     end if
  393.     hptr = x
  394.     end if
  395.     if prev then
  396.     lines[prev][NEXTL] = next
  397.     if next then
  398.         lines[next][PREVL] = prev
  399.     end if
  400.     else
  401.     eptr = next
  402.     if eptr then
  403.         lines[eptr][PREVL] = 0
  404.     end if
  405.     end if
  406. end procedure
  407.  
  408. function digits(natural x)
  409. -- return the 3-digits in number x
  410.     three_digits d
  411.  
  412.     d = {0, 0, 0}
  413.     while x >= 100 do
  414.     d[1] = d[1] + 1
  415.     x = x - 100
  416.     end while
  417.  
  418.     while x >= 10 do
  419.     d[2] = d[2] + 1
  420.     x = x - 10
  421.     end while
  422.  
  423.     d[3] = x
  424.     return d
  425. end function
  426.  
  427.  
  428. procedure PrintMove(move_number move)
  429. -- print the move that was just made
  430.     three_digits d
  431.     integer px, py
  432.  
  433.     d = digits(move)
  434.     py = (d[1] - 1) * 4.5 * SQUARE_SIZE + (d[2]-1) * SQUARE_SIZE + TOP_LEFT[2]
  435.     px = (d[1] - 1) * 2.5 * SQUARE_SIZE + (d[3]-1) * SQUARE_SIZE + TOP_LEFT[1]
  436.     mouse_pointer(OFF)
  437.     for i = 1 to 3 do
  438.     ellipse(GRAY, 1, {px+1, py+1}, 
  439.               {px + SQUARE_SIZE - 2, py + SQUARE_SIZE - 2})
  440.     Delay(70)
  441.     ellipse(pcolors[player], 1, {px+1, py+1}, 
  442.                     {px + SQUARE_SIZE - 2, py + SQUARE_SIZE - 2})
  443.     Delay(70)
  444.     end for
  445.     mouse_pointer(ON)
  446.     if endgame then
  447.     return
  448.     end if
  449.     if player = COMPUTER then
  450.     cmoves = cmoves + 1
  451.     else
  452.     hmoves = hmoves + 1
  453.     end if
  454. end procedure
  455.  
  456.  
  457. procedure Another(line x)
  458. -- add to the number of positions occupied by a player
  459. -- along a line x
  460.     integer inarow
  461.  
  462.     inarow = lines[x][COUNT] + 1
  463.     lines[x][COUNT] = inarow
  464.     if inarow < 4 then
  465.     return
  466.     end if
  467.     position(21,6)
  468.     text_color(BRIGHT_RED)
  469.     puts(SCREEN, pname[player])
  470.     puts(SCREEN, " WINS!          ")
  471.     text_color(BRIGHT_YELLOW)
  472.     endgame = TRUE
  473.     mouse_pointer(OFF)
  474.     for i = 1 to 4 do
  475.     for j = POS1 to POS4 do
  476.         PrintMove(lines[x][j])
  477.     end for
  478.     Delay(80)
  479.     end for
  480.     mouse_pointer(ON)
  481. end procedure
  482.  
  483.  
  484. procedure Delete_c(line x)
  485. -- delete from computer list
  486.     line prev, next
  487.  
  488.     prev = lines[x][PREVL]
  489.     next = lines[x][NEXTL]
  490.     if prev then
  491.     lines[prev][NEXTL] = next
  492.     else
  493.     cptr = next
  494.     end if
  495.     if next then
  496.     lines[next][PREVL] = prev
  497.     end if
  498. end procedure
  499.  
  500.  
  501. procedure Delete_h(line x)
  502. -- delete from human list
  503.     line prev, next
  504.  
  505.     prev = lines[x][PREVL]
  506.     next = lines[x][NEXTL]
  507.     if prev then
  508.     lines[prev][NEXTL] = next
  509.     else
  510.     hptr = next
  511.     end if
  512.     if next then
  513.     lines[next][PREVL] = prev
  514.     end if
  515. end procedure
  516.  
  517.  
  518. procedure init()
  519. -- initialize variables
  520.     integer temp, u, line, t
  521.  
  522.     clear_screen()
  523.     endgame = FALSE
  524.     cmoves = 0
  525.     hmoves = 0
  526.     for i = 1 to NLINES do
  527.     lines[i][STATUS] = EMPTY
  528.     lines[i][COUNT] = 0
  529.     end for
  530.     for i = 1 to NPOSITIONS do
  531.     positions[i][LINES_THRU] = 0
  532.     positions[i][AVAIL] = 0
  533.     end for
  534.     line = 1
  535.     for i = POS1 to POS4 do
  536.     lines[line][i] = (i-1) * 111
  537.     lines[line+1][i] = (i-1) * 109 + 5
  538.     lines[line+2][i] = (i-1) * 91 + 50
  539.     lines[line+3][i] = (i-1) * 89 + 55
  540.     end for
  541.     line = line + 4
  542.     for i = 1 to 4 do
  543.     for j = POS1 to POS4 do
  544.         lines[line][j] = i * 100 + (j-1) * 11
  545.         lines[line+1][j] = i * 100 + (j-1) * 9 + 5
  546.         lines[line+2][j] = (j-1) * 101 + i * 10
  547.         lines[line+3][j] = (j-1) * 99 + i * 10 + 5
  548.         lines[line+4][j] = (j-1) * 110 + i
  549.         lines[line+5][j] = (j-1) * 90 + 50 + i
  550.     end for
  551.     line = line + 6
  552.     end for
  553.     for i = 1 to 4 do
  554.     for j = 1 to 4 do
  555.         for k = POS1 to POS4 do
  556.         t = 100 * i + 10 * j + k - 1
  557.         u = (i - 1) * 16 + (j - 1) * 4 + k - 1
  558.         lp[t] = u
  559.         pl[u] = t
  560.         lines[line][k] = t
  561.         lines[line+1][k] = 100 * j + 10 * (k-1) + i
  562.         lines[line+2][k] = 100 * (k-1) + 10 * i + j
  563.         end for
  564.         line = line + 3
  565.     end for
  566.     end for
  567.     for i = 1 to NPOSITIONS do
  568.     positions[i][PREVP] = i - 1
  569.     positions[i][NEXTP] = i + 1
  570.     end for
  571.     positions[1][PREVP] = 0
  572.     positions[NPOSITIONS][NEXTP] = 0
  573.     fptr = 1
  574.     for i = 1 to NLINES do
  575.     lines[i][NEXTL] = i + 1
  576.     lines[i][PREVL] = i - 1
  577.     for j = POS1 to POS4 do
  578.         t = lines[i][j]
  579.         u = lp[t]
  580.         temp = positions[u][LINES_THRU] + 1
  581.         positions[u][LINES_THRU] = temp
  582.         positions[u][temp+1] = i
  583.     end for
  584.     end for
  585.     cptr = 0
  586.     hptr = 0
  587.     eptr = 0
  588.     lines[NLINES][NEXTL] = 0
  589.     lines[1][PREVL] = 0
  590.     for i = 1 to NPOSITIONS do
  591.     positions[i][NLIVE] = positions[i][LINES_THRU]
  592.     end for
  593.     position(15, 2)
  594.     text_color(COLORS[1])
  595.     puts(SCREEN, "3-D ")
  596.     text_color(COLORS[2])
  597.     puts(SCREEN, "tic ")
  598.     text_color(COLORS[3])
  599.     puts(SCREEN, "TAC ")
  600.     text_color(COLORS[4])
  601.     puts(SCREEN, "toe ")
  602. end procedure
  603.  
  604.  
  605. procedure UpdateMove(move_number m)
  606. -- update data structures after making move m
  607.     Position x1
  608.     line x2
  609.     integer prev, next, val, s
  610.  
  611.     x1 = lp[m]
  612.     positions[x1][AVAIL] = 1
  613.     prev = positions[x1][PREVP]
  614.     next = positions[x1][NEXTP]
  615.     if prev then
  616.     positions[prev][NEXTP] = next
  617.     if next then
  618.         positions[next][PREVP] = prev
  619.     end if
  620.     else
  621.     fptr = next
  622.     if fptr then
  623.         positions[fptr][PREVP] = 0
  624.     end if
  625.     end if
  626.     for j = LINE1 to 1+positions[x1][LINES_THRU] do
  627.     x2 = positions[x1][j]
  628.     s = lines[x2][STATUS]
  629.     if s = EMPTY then
  630.         lines[x2][STATUS] = player
  631.         lines[x2][COUNT] = 1
  632.         Relink(player, x2)
  633.     elsif s = COMPUTER then
  634.         if player = COMPUTER then
  635.         Another(x2)
  636.         else
  637.         lines[x2][STATUS] = DEAD
  638.         AdjValues(x2, -2)
  639.         Delete_c(x2)
  640.         end if
  641.     elsif s = HUMAN then
  642.         if player = HUMAN then
  643.         Another(x2)
  644.         if lines[x2][COUNT] = 2 then
  645.             val = 4
  646.         else
  647.             val = 0
  648.         end if
  649.         AdjValues(x2, val)
  650.         else
  651.         if lines[x2][COUNT] > 1 then
  652.             val = -5
  653.         else
  654.             val = -1
  655.         end if
  656.         lines[x2][STATUS] = DEAD
  657.         AdjValues(x2, val)
  658.         Delete_h(x2)
  659.         end if
  660.     end if
  661.     end for
  662. end procedure
  663.  
  664.  
  665. function Think()
  666. -- pick the best move, return {move, reason for it}
  667.     integer m, mymoves, myptr, me, him, hisptr, hismoves
  668.  
  669.     found = FALSE
  670.     if player = COMPUTER then
  671.     mymoves = cmoves
  672.     hismoves = hmoves
  673.     myptr = cptr
  674.     hisptr = hptr
  675.     me = COMPUTER
  676.     him = HUMAN
  677.     else
  678.     mymoves = hmoves
  679.     hismoves = cmoves
  680.     myptr = hptr
  681.     hisptr = cptr
  682.     me = HUMAN
  683.     him = COMPUTER
  684.     end if
  685.  
  686.     -- Have I got 3 in a row?
  687.     if mymoves >= 3 then
  688.     x = myptr
  689.     while x do
  690.         if lines[x][COUNT] = 3 then
  691.         return {Get4th(), 9}
  692.         end if
  693.         x = lines[x][NEXTL]
  694.     end while
  695.     end if
  696.  
  697.     -- Does the other guy have 3 in a row?
  698.     if hismoves >= 3 then
  699.     x = hisptr
  700.     while x do
  701.         if lines[x][COUNT] = 3 then
  702.         return {Get4th(), 1}
  703.         end if
  704.         x = lines[x][NEXTL]
  705.     end while
  706.     end if
  707.  
  708.     -- Do I have a 2x2 force?
  709.     if mymoves >= 4 then
  710.     x = myptr
  711.     l2 = 1
  712.     while x do
  713.         if lines[x][COUNT] = 2 then
  714.         m = Find2()
  715.         if found then
  716.             return {m, 2}
  717.         end if
  718.         end if
  719.         x = lines[x][NEXTL]
  720.     end while
  721.  
  722.     -- Do I have a 3-2-2-1 force ?
  723.     x = eptr
  724.     l2 = me
  725.     while x do
  726.         m = FindA()
  727.         if found then
  728.         return {m, 3}
  729.         end if
  730.         x = lines[x][NEXTL]
  731.     end while
  732.  
  733.     -- do I have a 3-2-2 force?
  734.     if mymoves >= 5 then
  735.         x = myptr
  736.         while x do
  737.         if lines[x][COUNT] = 1 then
  738.             m = FindB()
  739.             if found then
  740.             return {m, 4}
  741.             end if
  742.         end if
  743.         x = lines[x][NEXTL]
  744.         end while
  745.     end if
  746.     end if
  747.  
  748.     -- does the other guy have a 2x2 force?
  749.     if hismoves >= 4 then
  750.     x = hisptr
  751.     l2 = 1
  752.     while x do
  753.         if lines[x][COUNT] = 2 then
  754.         m = Find2()
  755.         if found then
  756.             return {m, 5}
  757.         end if
  758.         end if
  759.         x = lines[x][NEXTL]
  760.     end while
  761.  
  762.     -- does the other guy have a 3-2-2-1 force?
  763.     x = eptr
  764.     l2 = him
  765.     while x do
  766.         m = FindA()
  767.         if found then
  768.         return {m, 6}
  769.         end if
  770.         x = lines[x][NEXTL]
  771.     end while
  772.  
  773.     -- does the other guy have a 3-2-2 force?
  774.     if hismoves >= 5 then
  775.         x = hisptr
  776.         while x do
  777.         if lines[x][COUNT] = 1 then
  778.             m = FindB()
  779.             if found then
  780.             return {m, 7}
  781.             end if
  782.         end if
  783.         x = lines[x][NEXTL]
  784.         end while
  785.     end if
  786.     end if
  787.     -- just pick the move with the most possibilities
  788.     return {FindMax(), 8}
  789. end function
  790.  
  791.  
  792. procedure Setup()
  793. -- create major sequences
  794.     object name
  795.  
  796.     positions = repeat(repeat(0, 12), NPOSITIONS)
  797.     lines = repeat(repeat(0, 8), NLINES)
  798.     lp = repeat(0, 444)
  799.     pl = repeat(0, 64)
  800.     dbl = repeat(0, 52)
  801.     ptype = repeat(0, 4)
  802.     pname = ptype
  803.     ptype[1] = COMPUTER
  804.     ptype[2] = COMPUTER
  805.     pname[1] = "DEFENDO"
  806.     pname[2] = "AGGRESSO"
  807.     position(15, 1)
  808.     puts(SCREEN, " Name of player 1? (cr for DEFENDO) ")
  809.     name = gets(KEYB)
  810.     name = name[1..length(name)-1]
  811.     humans = 0
  812.     if length(name) > 0 then
  813.     pname[1] = name
  814.     ptype[1] = HUMAN
  815.     humans = humans + 1
  816.     end if
  817.     puts(SCREEN, "\n Name of player 2? (cr for AGGRESSO) ")
  818.     name = gets(KEYB)
  819.     name = name[1..length(name)-1]
  820.     if (length(name) > 0) then
  821.     pname[2] = name
  822.     ptype[2] = HUMAN
  823.     humans = humans + 1
  824.     end if
  825. end procedure
  826.  
  827. procedure draw_plane(integer color, integer x, integer y)
  828. -- draw one plane of the board
  829.      for i = 0 to 4 do
  830.     draw_line(color, {{x, y+i*SQUARE_SIZE}, 
  831.               {x+4*SQUARE_SIZE, y+i*SQUARE_SIZE}})
  832.      end for
  833.      for i = 0 to 4 do
  834.     draw_line(color, {{x+i*SQUARE_SIZE, y},
  835.               {x+i*SQUARE_SIZE, y+4*SQUARE_SIZE}})
  836.      end for
  837. end procedure
  838.  
  839. procedure make_board(sequence top_left)
  840. -- display the board
  841.     bk_color(8)
  842.     for i = 0 to 3 do
  843.     draw_plane(COLORS[i+1], top_left[1]+2.5*SQUARE_SIZE*i, 
  844.                 top_left[2]+4.5*SQUARE_SIZE*i)
  845.     end for
  846. end procedure
  847.  
  848. procedure ttt()
  849. -- this is the main routine
  850.     sequence m
  851.  
  852.     Setup()
  853.     player = rand(2) -- first game is random 
  854.              -- loser goes first in subsequent games
  855.     while TRUE do
  856.     mouse_pointer(OFF)
  857.     init()
  858.     make_board(TOP_LEFT)
  859.     mouse_pointer(ON)
  860.     text_color(BRIGHT_YELLOW)
  861.     mouse_events(LEFT_DOWN)
  862.     while endgame = FALSE do
  863.         if fptr then
  864.         if ptype[player] = HUMAN then
  865.             m = {GetMove()}
  866.         else
  867.             m = Think()
  868.             Why(m[2])
  869.         end if
  870.         PrintMove(m[1])
  871.         UpdateMove(m[1])
  872.         player = 3 - player
  873.         else
  874.         position(18,1)
  875.         puts(SCREEN, " A DRAW             ")
  876.         Delay(500)
  877.         exit
  878.         end if
  879.     end while
  880.     position(19, 1)
  881.     text_color(BRIGHT_MAGENTA)
  882.     puts(SCREEN, " Another game? (y or n) ")
  883.     text_color(BRIGHT_YELLOW)
  884.     if find('n', gets(KEYB)) then
  885.         exit
  886.     end if
  887.     end while
  888. end procedure
  889.  
  890. if graphics_mode(18) then -- VGA
  891.     puts(1, "VGA graphics is required\n")
  892. else
  893.     ttt()
  894. end if
  895.  
  896. if graphics_mode(-1) then
  897. end if
  898.  
  899.