home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_07_03 / v7n3034a.txt < prev    next >
Text File  |  1989-03-05  |  19KB  |  659 lines

  1. # Makefile for the Connect Four Game c4 - Charlie Havener
  2. HEADERS=vt100.h c4.h 
  3.  
  4. c4.obj: c4.c $(HEADERS)
  5.     cl /Zi /Dbugprint /c c4.c
  6.  
  7. c4ab.obj: c4ab.c $(HEADERS)
  8.     cl /Zi /Dbugprint /c  c4ab.c
  9.  
  10. c4move.obj: c4move.c $(HEADERS)
  11.     cl /Zi /Dbugprint /c c4move.c
  12.  
  13. c4subs.obj: c4subs.c $(HEADERS)
  14.     cl /Zi /Dbugprint /c c4subs.c
  15.  
  16. c4.exe: c4.obj c4move.obj c4subs.obj c4ab.obj
  17.     cl /Zi /Dbugprint c4.obj c4move.obj c4subs.obj c4ab.obj
  18.  
  19. /* c4.h header file for Connect Four Game program */
  20. #define XSIZE       7
  21. #define YSIZE       6
  22. #define NEWDISPLAY     1
  23. #define RED         1
  24. #define BLACK       2
  25. #define PLAYABLE    3
  26. #define EMPTY       0
  27. #define YOUWIN         1
  28. #define IWIN        2
  29. #define TIE         3
  30. #define YOURMOVE    4
  31. #define VT100       100
  32. #define TTY         50
  33. #define FALSE         0
  34. #define TRUE         1
  35. #define NIL         0
  36. #define ILLEGAL        -1
  37.  
  38. /* This is a rather clever debug print macro */
  39. #ifdef bugprint
  40. #define Debug(a,b) if ( debuglevel >= (a) ) printf b;
  41. #else
  42. #define Debug(a,b)
  43. #endif
  44.  
  45. /*  some ANSI  escape sequence codes */
  46. #define CURHOM    "\033[H"  /* home the cursor */
  47. #define CURSAV    "\033[s"  /* save the present location of the cursor */
  48. #define CURRES    "\033[u"  /* restore cursor to the saved location */
  49. #define EAOP    "\033[2J" /* erase all of page */
  50.  
  51. void init();
  52. int move();
  53. void display();
  54. int askmove();
  55. int c4move();
  56. int c4tie();
  57.  
  58. /* c4.c - main program for the Connect Four Game, The object 
  59. is to get 4 checkers in a row horizontally, vertically or diagonally
  60. on a 6 vertical by 7 horizontal checker board. Checkers enter at the
  61. top of the 7 columns only. The alpha-beta pruning algorithm is used.
  62. Charles D. Havener Dec 1988 */
  63.  
  64. #include <stdio.h>
  65. #include "c4.h"
  66.  
  67. /* All the global variables are defined here */
  68. int bd[XSIZE][YSIZE]={0};   /* the board representation */
  69. int search_depth=2;         /* the maximum depth of search allowed */
  70. int debuglevel = 0;         /* controls amount of debug printout */
  71. int cpu_move = ILLEGAL;        /* the last move chosen by the computer */
  72. int terminal_type=TTY ;     /* only TTY used now, future expansion */
  73.  
  74. /*-----------------------------------------------------------*/
  75. main(argc,argv)
  76.     int argc;
  77.     char *argv[];
  78.     {
  79.     int status = YOURMOVE;
  80.     int player[22];    /* at most each player can make 21 moves */
  81.     int computer[22];  /* this is the history of the moves */
  82.     int turn = 0;
  83.     int mv = 0;
  84.     int replay = FALSE; /* set TRUE if instant replay in progress */
  85.     char buf[40];
  86.  
  87.     if ( argc == 2 )
  88.     search_depth = atoi(argv[1]);
  89. begin:
  90.     if ( search_depth < 1 || search_depth > 8 )
  91.     fatal("\n search_depths must be between 1 and 8 \n");
  92.     init();
  93.     turn = 0;
  94.     status = YOURMOVE;
  95.     printf("%s%s",EAOP,"Welcome to CONNECT FOUR Version 1.1\n");
  96.     display(bd,NEWDISPLAY,terminal_type);
  97.     do      /* henceforth the player is RED & goes 1st, cpu is BLACK */
  98.     {
  99.     if ( replay )
  100.         {
  101.         mv = player[turn];
  102.         move(mv,RED,bd);
  103.         }
  104.     else
  105.         mv = askmove(RED);
  106.     if ( mv != ILLEGAL )
  107.         {
  108.         status = c4move(BLACK); /* cpu moves & returns status */
  109.         display(bd,NEWDISPLAY,terminal_type);
  110.         if ( replay )
  111.         {
  112.         if ( cpu_move != computer[turn] )
  113.             {
  114.             replay = FALSE;
  115.             printf("\n Different computer move! \n");
  116.             }
  117.         }
  118.         player[turn] = mv;
  119.         computer[turn++] = cpu_move;
  120.         switch ( status )
  121.         {
  122.         case YOUWIN:    printf("You Win Lucky\n");
  123.                 break;
  124.         case IWIN:      printf("I win. I'm so smart!\n") ;
  125.                 break;
  126.         case TIE:       printf("Amazing - a tie!\n");
  127.                 break;
  128.         case YOURMOVE:
  129.         default:
  130.             break;
  131.         }
  132.         }
  133.     } while ( status == YOURMOVE ) ;
  134.  
  135.     printf("\nPlayer   ");
  136.     for ( mv=0; mv < turn ; mv++ )
  137.     printf(" %d",player[mv]);
  138.     printf("\nComputer ");
  139.     for ( mv=0; mv < turn ; mv++ )
  140.     printf(" %d",computer[mv]);
  141.     printf("\nThank you for the game at depth %d\n",search_depth); 
  142.     printf("For instant replay at new search depth,\n");
  143.     printf("Enter depth 1 to 8 (0 to quit): ");
  144.     gets(buf);
  145.     search_depth = atoi(buf);
  146.     if ( search_depth != 0 )
  147.     {
  148.     replay = TRUE;
  149.     goto begin;
  150.     }
  151.     return 0;
  152.     }
  153. /* c4ab.c - This is the alpha-beta algorithm for the Connect Four
  154. game. f2() and g2() stop generate() of new boards if a win or loss
  155. has occured on the brd. Static evaluator tests for loss first and
  156. the initial value of bestmove was made illegal if the c4pick()
  157. function didn't choose a move.
  158. */
  159. #include "c4.h"
  160. static int bestmove = ILLEGAL;  /* will be picked by computer */
  161. static int nstats = 0;        /* number of static evaluations */
  162. extern int bd[XSIZE][YSIZE];
  163. extern int terminal_type;
  164. extern int debuglevel;
  165. extern int search_depth;
  166. int suckertrap();
  167. int earlywarning();
  168. int evalbd();
  169. int *c4cpy();
  170. void generate();
  171.  
  172. /*-------------------------------------------------------------------*/
  173. /* f2 - the alpha beta maximizer algorithm from Knuth's paper AI 1975*/
  174. int f2(brd,alpha,beta,depth,maxdepth)
  175.     int brd[XSIZE][YSIZE];  /* apologies to lint for passing in int* */
  176.     int alpha;
  177.     int beta;
  178.     int depth;
  179.     int maxdepth;
  180.     {
  181.     int m,t,x,i;
  182.     int *q;
  183.     int *boards[XSIZE+1];  /* filled in by generate() */
  184.     int play[XSIZE];       /* filled in by generate() */
  185.  
  186.     q = NIL;
  187.     Debug(1,("\n in f2() a=%d b=%d",alpha,beta))
  188.     if ( depth < maxdepth & !( c4won(BLACK,brd) || c4won(RED,brd) ) )
  189.     {
  190.     generate(boards,play,brd,depth+1); /* generate new boards */    
  191.             /* no imbedded NILs. Last one NIL for sure */
  192.     i = 0;
  193.     q = boards[ i++ ];      /* i.e. q = first(p) Knuths notation */
  194.     }
  195.     if ( q == NIL )
  196.     {
  197.     m =  stateval(brd); /* no legal moves or at maxdepth */
  198.     Debug(1,("\nLeaving f2 stateval = m =%d",m))
  199.     return m;
  200.     }
  201.     m = alpha;
  202.     while ( q != NIL && m < beta )
  203.     {
  204.     t = g2(q,m,beta,depth+1,maxdepth);
  205.     if ( t > m )
  206.         {
  207.         m = t;
  208.         if ( depth == 0 ) /* save the best move! */
  209.         bestmove = play[i-1];  /* c4pick uses bestmove */
  210.         }
  211.     q = boards[ i++ ]; /* q = next(q) Knuth */
  212.     }
  213.     for ( x=0 ; boards[x] ; x++ )  /* test for non NIL before freeing */
  214.     free( boards[x] );      /* recover memory space */
  215.     Debug(1,("\nLeaving f2 m=%d",m))
  216.     return m;
  217.     }
  218. /*-------------------------------------------------------------------*/
  219. /* g2 - the alpha beta minimizer algorithm from Knuth's paper AI 1975*/
  220. g2(brd,alpha,beta,depth,maxdepth)
  221.     int brd[XSIZE][YSIZE];
  222.     int alpha;
  223.     int beta;
  224.     int depth;
  225.     int maxdepth;
  226.     {
  227.     int m,t,x,i;
  228.     int *q;
  229.     int *boards[XSIZE+1]; /* filled in by generate, last slot NIL */
  230.     int play[XSIZE];
  231.  
  232.     q = NIL;
  233.     Debug(1,("\n in g2() a=%d b=%d",alpha,beta))
  234.     if ( depth < maxdepth & !( c4won(BLACK,brd) || c4won(RED,brd) ) )
  235.     {
  236.     generate(boards,play,brd,depth+1);
  237.             /* fills boards array with ptrs to boards */
  238.             /* no imbedded NILs. Last one NIL for sure */
  239.     i = 0;
  240.     q = boards[ i++ ];      /* i.e. q = first(p) Knuths notation */
  241.     }
  242.     if ( q == NIL )
  243.     {
  244.     m =  stateval(brd); /* no legal moves or at maxdepth */
  245.     Debug(1,("\nLeaving g2 stateval = m =%d",m))
  246.     return m;
  247.     }
  248.     m = beta;
  249.     while ( q != NIL && m > alpha )
  250.     {
  251.     t = f2(q,alpha,m,depth+1,maxdepth);
  252.     if ( t < m )
  253.         m = t;
  254.     q = boards[ i++ ]; /* q = next(q) Knuth */
  255.     }
  256.     for ( x=0 ; boards[x] ; x++ )  /* test for non NIL before freeing */
  257.     free( boards[x] );      /* recover memory space */
  258.     Debug(1,("\nLeaving g2 m=%d",m))
  259.     return m;
  260.     }
  261. /*---------------------------------------------------------------------*/
  262. /* generate - given a brd, fill in array of ptrs with next legal moves */
  263. void generate(positions,play,brd,depth)
  264.     int play[XSIZE];
  265.     int *positions[XSIZE+1];
  266.     int brd[XSIZE][YSIZE];
  267.     int depth;
  268.     {
  269.     int x;
  270.     int i;
  271.     int *p;
  272.     static int plausible_moves[XSIZE] = {3,4,2,1,5,0,6};
  273.  
  274.     Debug(2,("\n gen depth=%d ",depth))
  275.     for ( x=0 ; x<= XSIZE ; x++ )
  276.     positions[x] = NIL;
  277.     for ( x=0, i=0 ; x<XSIZE ; x++ )
  278.     {
  279.     p = c4cpy(brd); /* allocates space and copys brd into it */
  280.     if ( move(plausible_moves[x],(depth & 01 ? BLACK : RED ),p) )
  281.         {
  282.         play[i] = plausible_moves[x];
  283.         positions[i++] = p;     /* legal move made */
  284.         }
  285.     else
  286.         free(p);        /* recover space */
  287.     }
  288.     }
  289. /*-------------------------------------------------------------------*/
  290. /* stateval - static evaluation of brd position, high good for BLACK */
  291. stateval(brd)
  292.     int brd[XSIZE][YSIZE];
  293.     {
  294.     int x,y;
  295.     int score=100;        /* nominal score */
  296.  
  297.     ++nstats;       /* increment total number of static evals */
  298.     if ( debuglevel && terminal_type == VT100 )
  299.     display(brd,NEWDISPLAY,terminal_type);
  300.     for ( x=0 ; x<XSIZE ; x++ )
  301.     move(x,PLAYABLE,brd);   /* mark playable spots */
  302.     if ( c4won(RED,brd) )
  303.     score = 0;
  304.     else if ( c4won(BLACK,brd) )
  305.     score = 1000.;
  306.     else if (suckertrap(brd) )
  307.     score = 2;              /* very bad for BLACK */
  308.     else if ( earlywarning(brd) )
  309.     score = 4;              /* also bad for BLACK */
  310.     else
  311.     {
  312.     for ( x=2 ; x<5 ; x++ )
  313.         for ( y=0 ; y<YSIZE ; y++ )
  314.         {
  315.         if ( brd[x][y] == BLACK )
  316.             {
  317.             score += 3;
  318.             if ( x == 3 )
  319.             score += 3;
  320.             }
  321.         else if ( brd[x][y] == RED )
  322.             {
  323.             score--;
  324.             if ( x == 3 )
  325.             score--;
  326.             }
  327.         else
  328.             break;  /* rest of column EMPTY */
  329.         }
  330.     x = 3;  /* most wins will start and pass thru the center col */
  331.     for ( y=0; y<YSIZE ; y++ )
  332.         {
  333.         score += 5*evalbd(x,y,BLACK,brd,3);
  334.         score -= 3*evalbd(x,y,RED,brd,3);
  335.         }
  336.     }
  337.     return score;
  338.     }
  339. /*---------------------------------------------------------*/
  340. /* suckertrap - tests for 3 in row with both ends PLAYABLE */
  341. int suckertrap(brd)
  342.     int brd[XSIZE][YSIZE];
  343.     {
  344.     int x,y=0;
  345.  
  346.     for ( y=0 ; y<YSIZE ; y++ )
  347.     {
  348.     for ( x=0 ; x<XSIZE-4 ; x++ )
  349.         {
  350.         if ( brd[x][y] == PLAYABLE && brd[x+1][y] == RED
  351.         && brd[x+2][y] == RED && brd[x+3][y] == RED
  352.         && brd[x+4][y] == PLAYABLE )
  353.             return TRUE;
  354.         }
  355.     }
  356.     return FALSE;
  357. }
  358. /*----------------------------------------------------------------*/
  359. /* earlywarning - early warning of suckertrap, 2 PLAYABLE on ends */
  360. int earlywarning(brd)
  361.     int brd[XSIZE][YSIZE];
  362.     {
  363.     int x,y;
  364.  
  365.     for ( y=0 ; y<YSIZE ; y++ )
  366.     {
  367.     for ( x=0 ; x<XSIZE-5 ; x++ )
  368.         {
  369.         if ( brd[x][y] == PLAYABLE && brd[x+1][y] == PLAYABLE
  370.         && brd[x+2][y] == RED && brd[x+3][y] == RED
  371.         && brd[x+4][y] == PLAYABLE && brd[x+5][y] == PLAYABLE)
  372.             return TRUE;
  373.         }
  374.     }
  375.     return FALSE;
  376.     }
  377. /*------------------------------------------------------------------*/
  378. /* c4cpy - allocates space for new brd, copies into it, returns ptr */
  379. int *c4cpy(brd)
  380.     int brd[XSIZE][YSIZE];
  381.     {
  382.     int *p;
  383.  
  384.     p = (int *)malloc(XSIZE*YSIZE*2);
  385.     if ( p == 0 )
  386.     fatal("Could not allocate more board space");
  387.     memmove(p,brd,sizeof(bd) );
  388.     return p;
  389.     }
  390. /*----------------------------------------------------------------*/
  391. /* c4pick - picks the computers move by calling alpha-beta search */
  392. int c4pick(color)
  393.     int color;
  394.     {
  395.     int score;
  396.     long max = 7;
  397.     int k = search_depth;;
  398.  
  399.     nstats = 0;     /* zero total number of static evals counter */
  400.     while ( --k )
  401.     max *= 7;  /* 7 to the search_depth is max no. boards */
  402.     bestmove = ILLEGAL;  /* insures illegal if f2 fails to pick one */
  403.     score = f2(bd,-30000,30000,0,search_depth); /* call a-b algorithm */
  404.     printf("\n Score = %d #static evals=%d out of %ld\n",score,nstats,max); 
  405.     return bestmove;
  406.     }
  407. /*--------------------------------------------------------------*/
  408. /* evalbd - evaluates if N in a row is present in any direction */
  409. int evalbd(x,y,color,brd,in_a_row)
  410.     int in_a_row;
  411.     int x,y;
  412.     int color;
  413.     int brd[XSIZE][YSIZE];
  414.     {
  415.     int d[8];     /* number of squares in each of 8 directions */
  416.     int deltax,deltay = -1;
  417.     int k,xx,yy,attack_lines,i = 0;
  418.  
  419.     for ( deltax = -1 ; deltax<2 ; ++deltax )
  420.        {
  421.        for ( deltay = -1 ; deltay<2 ; ++deltay )
  422.         {
  423.         if ( deltax == 0  && deltay == 0 )
  424.             ++deltay;       /* or you may loop 'till doomsday */
  425.         for (k=0,xx=x,yy=y ; (0 <= xx) && (xx < XSIZE)
  426.          && (0<=yy) && (yy<YSIZE) ; xx += deltax,yy += deltay)
  427.         {
  428.         if ( brd[xx][yy] == color )
  429.             {
  430.             if ( ++k == in_a_row )
  431.             break;
  432.             }
  433.         else
  434.             break;          /* escape the for loop */
  435.         }
  436.         if ( k > 0 )
  437.         d[i++] = --k;   /* save no. of squares in this direc */
  438.                 /* Dont count start square twice */
  439.         else
  440.         d[i++] = 0;
  441.         }
  442.        }
  443.     attack_lines = (1+ d[0] + d[7])  / in_a_row  /* right diagonal */
  444.                + (1+ d[1] + d[6]) / in_a_row /* horizontal */
  445.            + (1+ d[2] + d[5])/in_a_row   /* left diagonal */
  446.            + (1 + d[3] + d[4])/in_a_row ; /* vertical */
  447.     return attack_lines;  /* how many lines of N in a row attacks */
  448.     }
  449. /*       score table
  450.         dx      dy      i       direction
  451.         -1      -1      0       /  left down
  452.         -1      0       1       <-----
  453.         -1      1       2       \  left up
  454.         0       -1      3       |  down
  455.         0       0       skipped
  456.         0       1       4       |  up
  457.         0       -1      5       \  right down
  458.         1       0       6       --->
  459.         1       1       7       /  right up
  460. used in computing score
  461. */
  462. /* c4move.c - makes and checks moves on the board for legality etc */
  463. #include <stdio.h>
  464. #include "c4.h"
  465. extern int bd[XSIZE][YSIZE];
  466. extern int cpu_move;
  467.  
  468. /*-----------------------------------------------------------*/
  469. /* c4move - this routine picks the cpu's move - calls c4pick */
  470. int c4move(mycolor)
  471.     int mycolor;
  472.     {
  473.     int hiscolor,x;
  474.  
  475.     if ( mycolor == BLACK )
  476.     hiscolor = RED;
  477.     else
  478.     hiscolor = BLACK;
  479.     if ( c4won(hiscolor,bd) )       /* check if he just won! */
  480.     return YOUWIN;
  481.     if ( c4tie() )                  /* any moves left for computer? */
  482.     return TIE;
  483.     x = c4pick(mycolor);    /* invokes alpha-beta search algorithm */
  484.     cpu_move = x;
  485.     if ( !move(x,mycolor,bd) )
  486.     {
  487.     printf("Illegal computer move [%d] attempted\n",x);
  488.     return YOUWIN;          /* computer move was illegal!? */
  489.     }
  490.     if ( c4won(mycolor,bd) )
  491.     return IWIN;
  492.     else if ( c4tie() )
  493.     return TIE;
  494.     else
  495.     return YOURMOVE;
  496.     }
  497. /*--------------------------------------------------*/
  498. /* c4won - returns TRUE if specified color just won */
  499. int c4won(color,brd)
  500.     int color;
  501.     int brd[XSIZE][YSIZE];
  502.     {
  503.     int k,x,y,xx,yy;
  504.     for ( x=0 ; x < XSIZE ; x++ )
  505.     {
  506.     for ( y=0 ; y < YSIZE ; y++ )
  507.         {
  508.         if ( brd[x][y] == color )
  509.         {
  510.         for ( k=0, xx=x ; xx < XSIZE ; xx++ ) /* horizontal */
  511.             {
  512.             if ( brd[xx][y] != color )
  513.                 break;
  514.             if ( ++k == 4 )
  515.                 return TRUE;
  516.             }
  517.         for ( k=0, yy=y ; yy<YSIZE ; yy++ ) /* vertical */
  518.             {
  519.             if ( brd[x][yy] != color )
  520.                 break;
  521.             if ( ++k == 4 )
  522.                 return TRUE;
  523.             }
  524.         for ( k=0,xx=x,yy=y ; xx<XSIZE && yy<YSIZE ; ++xx,++yy )
  525.             {
  526.             if ( brd[xx][yy] != color )
  527.                 break;
  528.             if ( ++k == 4 )
  529.                 return TRUE;
  530.             }
  531.         for ( k=0,xx=x,yy=y ; xx>=0 && yy<YSIZE ; --xx,++yy)
  532.             {
  533.             if ( brd[xx][yy] != color )
  534.                 break;
  535.             if ( ++k == 4 )
  536.                 return TRUE;
  537.             }
  538.         }
  539.         }
  540.     }
  541.     return FALSE;           /* specified color has not won */
  542.     }
  543. /*------------------------------------------------------------*/
  544. /* c4tie - returns TRUE if there are no moves left to be made */
  545. int c4tie()
  546.     {
  547.     int x;
  548.     for ( x=0 ; x<XSIZE ; ++x )
  549.     if (bd[x][YSIZE-1] == EMPTY )
  550.         return FALSE;
  551.     return TRUE;
  552.     }
  553. /* c4subs.c - misc routines needed by the Connect Four Game */
  554. #include "c4.h"
  555. #include <stdio.h>
  556. extern int bd[XSIZE][YSIZE];
  557. extern int terminal_type;
  558. /*------------------------------------------------------*/
  559. /* init - initializes the board to empty */
  560. void init()
  561.     {
  562.     int x,y = 0;
  563.     for ( x = 0 ; x < XSIZE ; x++ )
  564.         for ( y=0 ; y < YSIZE ; y++)
  565.             bd[x][y] = EMPTY;
  566.     }
  567. /*------------------------------------------------------*/
  568. /* move - makes the specified move on the board passed to it */
  569. int move(x,color,brd)
  570.     int x;
  571.     int color;
  572.     int brd[XSIZE][YSIZE];
  573.     {
  574.     int y = 0;
  575.  
  576.     if ( x >= 0  &&  x < XSIZE )
  577.         {
  578.         for ( y=0 ; y < YSIZE ; y++ )
  579.             {
  580.             if ( brd[x][y]  == EMPTY )
  581.                 {
  582.                 brd[x][y] = color;
  583.                 return TRUE;
  584.                 }
  585.             }
  586.         }
  587.     return FALSE;   /* Illegal move! */
  588.     }
  589. /*------------------------------------------------------*/
  590. /* fatal - prints out error message on stderr and exits */
  591. void fatal(message)
  592.     char *message;
  593.     {
  594.     fprintf(stderr,"\n%s\n",message);
  595.     exit(1);
  596.     }
  597. /*------------------------------------------------------*/
  598. /* display - updates the terminal display from the given array */
  599. void display(brd,option,term_type)
  600.     int brd[XSIZE][YSIZE];
  601.     int option,term_type;
  602.     {
  603.     int i,x,y;
  604.     if ( option == NEWDISPLAY && term_type == VT100 )
  605.         {
  606.         printf("%s%s",CURSAV,CURHOM);
  607.         }
  608.     printf("\n\t 0   1   2   3   4   5   6\n");
  609.     for ( y = YSIZE-1 ; y >= 0 ; y-- )
  610.         {
  611.         printf("\n\t");
  612.         for ( x = 0 ; x < XSIZE ; x++ )
  613.             {
  614.             i = brd[x][y];
  615.             if ( i == EMPTY )
  616.                 printf("__  ");
  617.             else if ( i == RED )
  618.                 printf("00  ");
  619.             else
  620.                 printf("XX  ");
  621.             }
  622.         }
  623.     if ( term_type == VT100 )
  624.         printf("%s",CURRES);
  625.     }
  626. /*------------------------------------------------------*/
  627. /* askmove - obtains players move and checks if valid */
  628. int askmove(color)
  629.     int color;
  630.     {
  631.     int x;
  632.     char string [80];
  633.     char *p;
  634.     extern int cpu_move;
  635.  
  636.     printf("\n\n");
  637.     if ( cpu_move >= 0 )
  638.         printf("                 My move = %d\n",cpu_move);
  639.     printf("Enter the column (0-6) for your move: ");
  640.     p = gets(string);
  641.     if ( p == 0 )
  642.         fatal("Game terminated by EOF");
  643.     if ( string[0] == '\014' )  /* Cntrl L */
  644.         {
  645.         printf("%s",EAOP);
  646.         display(bd,NEWDISPLAY,terminal_type);
  647.         return ILLEGAL;
  648.         }
  649.     x = string[0] - '0';
  650.     if ( move(x,color,bd) )
  651.         return x;
  652.     else
  653.         {
  654.         printf("\n Come on now that's an illegal move");
  655.         return ILLEGAL;
  656.         }
  657.     }
  658.  
  659.