home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / SIMTEL / CPMUG / CPMUG048.ARK / OTHELLO.C < prev    next >
C/C++ Source or Header  |  1984-04-29  |  11KB  |  527 lines

  1.  
  2. /*
  3.  
  4.     OTHELLO -- The Game of Dramatic Reversals
  5.  
  6.     written by Bert Halstead
  7.     modified for BDS C by Leor Zolman
  8.  
  9. This program is a good example of:
  10.  
  11.     a) structured, heirarchical function organization
  12.     b) arrays as formal parameters
  13.     c) use of the "qsort" library function
  14.  
  15.    Object of the game is for two players to alternate
  16. placing their marker someplace on an 8 by 8 grid, so that
  17. at least one of the opponent's pieces becomes surrounded
  18. by the moving player's peices -- causing the flanked pieces
  19. to flip 'color' and belong to the moving player. After 60
  20. moves have been played (or if no player has a legal move left),
  21. the player with the most of his own pieces on the board wins.
  22.  
  23.    The playing pieces are '*' and '@'. You may choose to play
  24. either '*' or '@' for the first game; thereafter, you and the
  25. computer will alternate going first for each game. Whoever
  26. goes first always plays `*'.
  27.  
  28.    You enter a move as a two digit number, each digit being
  29. from 1 to 8, first digit representing row and second representing
  30. column. For example: if playing '*', your first move might be '46',
  31. meaning 4th row down, 6th position across.
  32.  
  33.    As an alternative to entering a move, one of the following
  34. commands may be typed:
  35.  
  36.     g    causes computer to play both sides until game
  37.         is over
  38.  
  39.     a    causes computer to print out an analysis of
  40.         each of your possible moves. A letter from A
  41.         to Z will appear at each of your legal move
  42.         positions, where A is the machine's opinion
  43.         of an excellant move and Z is a real loser.
  44.  
  45.     hn    sets handicap. n is 1,2,3, or 4. If n is
  46.         positive, gives n free pieces to the computer.
  47.         If n is negative, gives YOU the free peices.
  48.  
  49.     f    forfeit the current move. This happens
  50.         automatically if you have no legal moves.
  51.  
  52.     q    quit the current game.
  53.  
  54.     b    prints out board again.
  55.  
  56.     s    prints out the score, and tells who is winning.
  57.  
  58. */
  59.  
  60.  
  61. #define BLACK '*'
  62. #define WHITE '@'
  63. #define EMPTY '-'
  64.  
  65.  
  66. int handicap;
  67. char selfplay;        /* true if computer playing with itself */
  68. int h[4][2];        /* handicap position table */
  69. char mine, his;        /* who has black (*) and white (@) in current game */
  70. char mefirst;        /* true if computer goes first in current game */
  71.  
  72. main(argc,argv)
  73. int argc;
  74. char **argv;
  75. {
  76.     char b[8][8];
  77.     int i;
  78.     h[0][0] = h[0][1] = h[2][0] = h[3][1] = 0;
  79.     h[1][0] = h[1][1] = h[2][1] = h[3][0] = 7;
  80.     printf("\nWelcome to the BDS C OTHELLO program!\n");
  81.     printf("\nNote: `*' always goes first...Good luck!!!\n\n");
  82.  
  83.     srand1("Do you want to go first? ");
  84.     if (toupper(getchar()) == 'Y') 
  85.         mefirst = 0;
  86.     else
  87.         mefirst = 1;
  88.  
  89.     printf("\n\n");
  90.  
  91.     do {
  92.         clrbrd(b);
  93.         prtbrd(b);
  94.         i = game(b,4);
  95.         mefirst = !mefirst;
  96.         if (i==4) break;
  97.         if (i=='Q') continue;
  98.         printf("\n");
  99.         i = prtscr(b);
  100.         if (i>0) printf(" You won by %d\n",i);
  101.         else if (i<0) printf(" You lost by %d\n",-i);
  102.         else printf(" A draw\n");
  103.     } while (ask("Another game? ")=='Y');
  104. }
  105.  
  106. game(b,n)
  107. char b[8][8];
  108. int n;
  109. {
  110.     char c;
  111.     int ff;
  112.     int i,j;
  113.     handicap = 0;
  114.     selfplay = ' ';
  115.     ff=0;
  116.  
  117.     if (mefirst) {
  118.         mine = BLACK; his = WHITE;
  119.         printf("\nI go first:\n\n");
  120.     }
  121.     else {
  122.         mine = WHITE; his = BLACK;
  123.         printf("\nYou go first:\n\n");
  124.     }
  125.  
  126.     while(1) {
  127.         if (cntbrd(b,EMPTY)==0) return 'D';
  128.         if (cntbrd(b,EMPTY)==60 && mine == BLACK) goto Istart;
  129.         if (chkmvs(b,his)==0) {
  130.             printf(!mefirst ? "Forfeit" : "   ...Forfeit\n");
  131.             ff |= 1;
  132.             }
  133.         else switch (c = getmov(&i,&j)) {
  134.         case 'B': prtbrd(b); continue;
  135.         case 'S': i= prtscr(b);
  136.             if (i>0) printf(" You're winning\n");
  137.             else if (i<0)printf(" You're losing!\n");
  138.             else putchar('\n');
  139.             continue;
  140.         case 'Q': case 4: return c;
  141.  
  142.         case 'H': if (n>abs(handicap)+4)
  143.                 printf("Illegal!\n");
  144.             else for (j=0; i!=0; j++) {
  145.              b[h[j][0]][h[j][1]]= i>0?BLACK:WHITE;
  146.              handicap += i>0 ? 1 : -1;
  147.              ++n;
  148.              i += i>0 ? -1 : 1;
  149.             }
  150.             prtbrd(b); continue;
  151.         case 'A': analyze(b,his,mine,EMPTY);
  152.             continue;
  153.         case 'G': my_mov(b,his,mine,EMPTY,&i,&j);
  154.         case 'M': if (chkmov(b,his,i,j)>0) {
  155.             printf(!mefirst ? "%1d-%1d" : "   ...%1d-%1d\n",
  156.                 i+1,j+1);
  157.             putmov(b,his,i,j);
  158.             }
  159.             else {
  160.               printf("Illegal!\n");
  161.               continue;
  162.              }
  163.             break;
  164.         case 'F': if (n>abs(handicap)+4) {
  165.             printf ("Illegal!\n");
  166.             continue;
  167.              }
  168.             else printf(!mefirst ? "Forfeit" :
  169.                          "   ...Forfeit\n");
  170.         }
  171. Istart:        if (cntbrd(b,EMPTY) == 0) return 'D';
  172.         if (chkmvs(b,mine)==0) {
  173.             printf(!mefirst ? "...Forfeit\n": "Forfeit...\n");
  174.             ff |=2;
  175.             }
  176.         else {
  177.             my_mov(b,mine,his,EMPTY,&i,&j);
  178.             printf(!mefirst ? "...%1d-%1d\n" : "%1d-%1d...\n",
  179.                 i+1,j+1);
  180.             putmov(b,mine,i,j);
  181.             ++n;
  182.             }
  183.         if (ff==3 || n>64) return 'D';
  184.         if (!(ff & 1)) prtbrd(b);
  185.         ff = 0;
  186.     }
  187. }
  188.  
  189.  
  190. prtscr(b)
  191. char *b;
  192. {
  193.     int i,j;
  194.     printf("%1d-%1d",i = cntbrd(b,his), j=cntbrd(b,mine));
  195.     return i-j;
  196. }
  197.  
  198. char getmov(i,j)
  199. int *i, *j;
  200. {
  201.     char a,c;
  202.     int n;
  203.     char *p;
  204.     char skipbl();
  205.     if (selfplay == 'G') {
  206.         if (!kbhit()) return 'G';
  207.         selfplay = ' ';
  208.         getchar();
  209.     }
  210.     printf("Move: ");
  211.     while(1) switch (c=skipbl()) {
  212.         case '\n': printf("Move?  "); continue;
  213.         case 'G': if ((c = skipbl()) != '\n')
  214.                 goto flush;
  215.             selfplay='G';
  216.             return 'G';
  217.         case 'B': case 'S': case 'Q':
  218.         case 'F': case 'A':
  219.           a=c;
  220.           if (( c = skipbl()) != '\n') goto flush;
  221.           return a;
  222.         case 'H': if ((a=c=skipbl()) == EMPTY)
  223.                 c=getchar();
  224.             if (c<'1' || c>'4' || skipbl() !='\n')
  225.                 goto flush;
  226.             *i = a==EMPTY? -(c-'0') : (c-'0');
  227.             return 'H';
  228.         case 4: return c;
  229.         default: if (c<'1' || c>'8') goto flush;
  230.             *i = c-'1';
  231.             c = skipbl();
  232.             if (c<'1' || c>'8') goto flush;
  233.             *j = c- '1';
  234.             if ((c=skipbl()) == '\n') return 'M';
  235.         flush:    while (c != '\n' && c != 4)
  236.                 c=getchar();
  237.             if (c==4) return c;
  238.             printf ("Huh?? ");
  239.         }
  240. }
  241.  
  242. char ask(s)
  243. char *s;
  244. {
  245.     char a,c;
  246.     printf ("%s ",s);
  247.     a=skipbl();
  248.     while (c != '\n' && c != 4) c= getchar();
  249.     return a;
  250. }
  251.  
  252. char skipbl()
  253. {
  254.     char c;
  255.     while ((c = toupper(getchar())) == ' ' || c=='\t');
  256.     return c;
  257. }
  258.  
  259.  
  260.  
  261. chkmvs(b,p)
  262. char b[8][8];
  263. char p;
  264. {
  265.     int i,j,k;
  266.     k=0;
  267.     for (i=0; i<8; i++) for (j=0; j<8; j++)
  268.         k += chkmov(b,p,i,j);
  269.     return k;
  270. }
  271.  
  272.  
  273. chkmov(b,p,x,y)
  274. char b[8][8],p;
  275. int x,y;
  276. {
  277.     if (b[x][y] != EMPTY) return 0;
  278.     return    chkmv1(b,p,x,y,0,1) + chkmv1(b,p,x,y,1,0) +
  279.         chkmv1(b,p,x,y,0,-1)+ chkmv1(b,p,x,y,-1,0)+
  280.         chkmv1(b,p,x,y,1,1) + chkmv1(b,p,x,y,1,-1)+
  281.         chkmv1(b,p,x,y,-1,1)+ chkmv1(b,p,x,y,-1,-1);
  282. }
  283.  
  284.  
  285. chkmv1(b,p,x,y,m,n)
  286. char b[8][8],p;
  287. int x,y,m,n;
  288. {
  289.     int k;
  290.     k=0;
  291.     while ((x += m) >= 0 && x < 8 && (y += n) >= 0 && y<8)
  292.     {
  293.         if (b[x][y]==EMPTY) return 0;
  294.         if (b[x][y]== p ) return k;
  295.         if (x==0 || x==7 || y==0 || y==7)
  296.             k += 10;
  297.          else k++;
  298.     }
  299.     return 0;
  300. }
  301.  
  302.  
  303. notake(b,p,o,e,x,y)
  304. char b[8][8];
  305. char p,o,e;
  306. int x,y;
  307. {
  308.     return notak1(b,p,o,e,x,y,0,1)&&
  309.         notak1(b,p,o,e,x,y,1,1)&&
  310.         notak1(b,p,o,e,x,y,1,0)&&
  311.         notak1(b,p,o,e,x,y,1,-1);
  312. }
  313.  
  314.  
  315. notak1(b,p,o,e,x,y,m,n)
  316. char b[8][8],p,o,e;
  317. int x,y,m,n;
  318. {
  319.     int c1,c2;
  320.     c1 = notak2(b,p,o,e,x,y,m,n);
  321.     c2 = notak2(b,p,o,e,x,y,-m,-n);
  322.     return !(c1==o && c2==e || c1==e && c2==o);
  323. }
  324.  
  325.  
  326. notak2(b,p,o,e,x,y,m,n)
  327. char b[8][8],p,o,e;
  328. int x,y,m,n;
  329. {
  330.     x += m; y +=n;
  331.     if (x>=0 && x<=7 && y>=0 && y<=7)
  332.         while(b[x][y] == 0) {
  333.          x += m; y+=n;
  334.          if (x<0 || x>7 || y<0 || y>7 || b[x][y]==e)
  335.             return o;
  336.          }
  337.     while (x>=0 && x<=7 && y>=0 && y<=7 && b[x][y]==p)
  338.             { x +=m; y+=n; }
  339.     if (x<0 || x>7 || y<0 || y>7) return p;
  340.     return b[x][y];
  341. }
  342.  
  343.  
  344. putmov(b,p,x,y)
  345. char b[8][8];
  346. char p;
  347. int x,y;
  348. {
  349.     int i,j;
  350.     b[x][y] = p;
  351.     for (i= -1; i<=1; i++) for (j= -1; j<=1; j++) {
  352.         if ((i != 0 || j!=0)&&chkmv1(b,p,x,y,i,j)>0)
  353.             putmv1(b,p,x,y,i,j);
  354.      }
  355. }
  356.  
  357.  
  358. putmv1(b,p,x,y,m,n)
  359. char b[8][8];
  360. char p;
  361. int x,y,m,n;
  362. {
  363.     while ((x += m) >= 0 && x<8 && (y += n)>=0 && y<8) {
  364.         if (b[x][y] == EMPTY || b[x][y] == p) return;
  365.         b[x][y] = p;
  366.      }
  367. }
  368.  
  369.  
  370. struct mt {
  371.         int x;
  372.         int y;
  373.         int c;
  374.         int s;
  375.      };
  376.  
  377. my_mov(b,p,o,e,m,n)
  378. char b[8][8],p;
  379. int *m, *n;
  380. {
  381.     struct mt  t[64];
  382.     int i,k;
  383.     int cmpmov();
  384.     k = fillmt(b,p,o,e,t);
  385.     if (!k) return 0;
  386.     qsort (&t, k, 8, &cmpmov);
  387.     for (i=1; i<k; i++)
  388.         if (t[i].s != t[0].s || t[i].c != t[0].c)
  389.                         break;
  390.     k = rand() % i;
  391.     *m = t[k].x;
  392.     *n = t[k].y;
  393.     return 1;
  394. }
  395.  
  396. analyze(b,p,o,e)
  397. char b[8][8], p,o,e;
  398. {
  399.     struct mt  t[64];
  400.     char a[8][8];
  401.     int i,k,c;
  402.     k = fillmt(b,p,o,e,t);
  403.     cpybrd(a,b);
  404.     for (i=0; i<k; i++)
  405.       a[t[i].x][t[i].y] = ((c = 'F' - t[i].s) <= 'Z')?c:'Z';
  406.     prtbrd(a);
  407. }
  408.  
  409.  
  410. fillmt(b,p,o,e,t)
  411. char b[8][8],p,o,e;
  412. struct mt  t[64];
  413. {
  414.     int i,j,k;
  415.     k = 0;
  416.     for (i=0; i<8; i++) for(j=0; j<8; j++)
  417.        if (t[k].c = chkmov(b,p,i,j)) {
  418.             t[k].x =i;
  419.             t[k].y =j;
  420.             t[k].s = s_move(b,p,o,e,i,j);
  421.             ++k;
  422.         }
  423.     return k;
  424. }
  425.  
  426.  
  427.  
  428. s_move(b,p,o,e,i,j)
  429. char b[8][8], p, o, e;
  430. int i,j;
  431. {
  432.     char a[8][8];
  433.     int ok,s,k,l,side,oside;
  434.     int c,dkl;
  435.     cpybrd(a,b);
  436.     putmov(a,p,i,j);
  437.     side = 0;
  438.     if (i==0 || i==7) side++;
  439.     if (j==0 || j==7) side++;
  440.     s = 0;
  441.     ok = 0;
  442.     if (side==2 || notake(b,p,o,e,i,j)) ok++;
  443.     oside = 0;
  444.     for (k=0; k<8; k++) for(l=0; l<8; l++)
  445.      {
  446.         c=chkmov(a,o,k,l);
  447.         if (c==0) continue;
  448.         dkl = 1;
  449.         if (k==0 || k==7) { dkl+=2; oside|=4;}
  450.         if (l==0 || l==7) {dkl+=2; oside|=4; }
  451.         if (dkl==5) {dkl = 10; oside |= 16; }
  452.             else if (!notake(a,o,p,e,k,l))
  453.                     continue;
  454.         oside |= 1;
  455.         s -= dkl;
  456.         if (c>=10) { s -= 4; oside |= 8; }
  457.         }
  458.     if (s< -oside) s= -oside;
  459.     if (side>0) return s+side-7+10*ok;
  460.     if (i==1 || i==6) {s--; side++;}
  461.     if (j==1 || j==6) {s--; side++;}
  462.     if (side>0) return s;
  463.     if (i==2 || i==5) s++;
  464.     if (j==2 || j==5) s++;
  465.     return s;
  466. }
  467.  
  468. cmpmov(a,b)
  469. struct mt  *a, *b;
  470. {
  471.     if ((*a).s > (*b).s) return -1;
  472.     if ((*a).s < (*b).s) return 1;
  473.     if ((*a).c > (*b).c) return -1;
  474.     if ((*a).c < (*b).c) return 1;
  475.     return 0;
  476. }
  477.  
  478.  
  479.  
  480. clrbrd(b)
  481. char b[8][8];
  482. {
  483.     int i,j;
  484.     for (i=0; i<8; i++)
  485.         for (j=0; j<8; j++)
  486.             b[i][j]= EMPTY;
  487.     b[3][3] = b[4][4] = BLACK;
  488.     b[3][4] = b[4][3] = WHITE;
  489. }
  490.  
  491.  
  492. prtbrd(b)
  493. char b[8][8];
  494. {
  495.     int i,j;
  496.     printf("   1 2 3 4 5 6 7 8\n");
  497.     for (i=0; i<8; i++) {
  498.         printf("%2d",i+1);
  499.         for (j=0; j<8; j++) {
  500.             putchar(' ');
  501.             putchar(b[i][j]);
  502.          }
  503.         putchar('\n');
  504.      }
  505.     putchar('\n');
  506. }
  507.  
  508.  
  509. cpybrd(a,b)
  510. char *a, *b;
  511. {
  512.     int i;
  513.     i=64;
  514.     while (i--)
  515.         *a++ = *b++;
  516. }
  517.  
  518. cntbrd(b,p)
  519. char *b, p;
  520. {
  521.     int i,j;
  522.     i= 64; j=0;
  523.     while (i--)
  524.         if (*b++ == p) ++j;
  525.     return (j);
  526. }
  527.