REV.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:8k
源码类别:

Windows编程

开发平台:

Visual C++

  1. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  2. //  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  3. //  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  4. //  PARTICULAR PURPOSE.
  5. //
  6. //  Copyright (C) 1993-1997  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  PROGRAM: Rev.c
  9. //
  10. //  PURPOSE: Helper functions for Reversi Sample Game
  11. //
  12. //  FUNCTIONS:
  13. //  finalscore() - Calculate final score
  14. //  legalcheck() - Return 1 if move legal, else return 0
  15. //  makemove() - Capture enemy pieces
  16. //  score() - Calculate the value of board
  17. //  minmax() - Play human move then recursively play computer move
  18. //
  19. //  SPECIAL INSTRUCTIONS: N/A
  20. //
  21. #include <windows.h>
  22. #include <windowsx.h>
  23. #include <process.h>
  24. #include <stdlib.h>
  25. #include "reversi.h"
  26. // declarations of function in reversi.c
  27. VOID NEAR PASCAL paintmove(BYTE b[BoardSize], INT move, INT friendly,
  28.     INT enemy);
  29. // variable declarations
  30. extern INT     moves[61];
  31. extern INT     BestMove[max_depth+2];
  32. extern HWND    hWin;
  33. extern HDC     hDisp;
  34. extern INT     depth;
  35. extern INT     direc[];
  36. //  Indexes for computing scores and whether or not a player has
  37. //  any pieces on the board.  Very order dependant.
  38. BYTE PieceFlags[] = {   0x00 ,      // Ignore sides
  39.             0x00 ,      // Ignore blanks
  40.             0x01 ,      // Human has a piece
  41.             0x02 ,      // Computer has a piece
  42.             };
  43.             
  44. //
  45. //  The scoring tables are used to evaluate the board
  46. //  position.  The corners of the board change value
  47. //  according to whether a given square is occupied or
  48. //  not.  This can be done dynamically, saving ~ 1K
  49. //  worth of data space but costing an as of yet
  50. //  undetermined performance hit.
  51. //
  52. #define B11     11    // Offsets to particular squares
  53. #define B18     18 
  54. #define B81     81 
  55. #define B88     88 
  56. #define maskb11     0x08    // Masks used for indexing into Scoring tables.
  57. #define maskb18     0x04
  58. #define maskb81     0x02
  59. #define maskb88     0x01
  60. //
  61. //  FUNCTION: finalscore()
  62. //
  63. //  PURPOSE:  Calculate final score
  64. //
  65. INT NEAR PASCAL finalscore(
  66. BYTE b[],
  67. BYTE friendly,
  68. BYTE enemy)
  69. {
  70.     INT i;
  71.     INT count=0;
  72.     for (i=11 ; i<=88 ; i++) {
  73.         if (b[i] == friendly)
  74.             count++;
  75.         else
  76.             if (b[i] == enemy)
  77.                 count--;
  78.     }
  79.     if (count > 0)
  80.         return(win + count);
  81.     else
  82.         if (count < 0)
  83.             return(loss + count);
  84.         else
  85.             return(0);
  86. }
  87. //
  88. //  FUNCTION: legalcheck()
  89. //
  90. //  PURPOSE:  Return 1 if move legal, else return 0
  91. //
  92. INT NEAR PASCAL legalcheck(
  93. BYTE b[],
  94. INT move,
  95. BYTE friendly,
  96. BYTE enemy)
  97. {
  98.    INT sq,d;
  99.    INT *p;
  100.    if (b[move] == empty) {
  101.       p=direc;
  102.       while ((d = *p++) != 0) {
  103.           sq=move;
  104.           if (b[sq += d] == enemy) {
  105.              while(b[sq += d] == enemy)
  106.             ;
  107.              if (b[sq] == friendly) return(1);
  108.           }
  109.       }
  110.    }
  111.    return(0);
  112. }
  113. //
  114. //  FUNCTION: makemove()
  115. //
  116. //  PURPOSE:  Capture enemy pieces
  117. //
  118. VOID NEAR PASCAL makemove(
  119. BYTE b[],
  120. INT move,
  121. BYTE friendly,
  122. BYTE enemy)
  123. {
  124.    INT sq,d;
  125.    INT *p;
  126.    if (move != PASS) {
  127.       p=direc;
  128.       while ((d = *p++) != 0) {
  129.           sq=move;
  130.           if (b[sq += d] == enemy) {
  131.             while(b[sq += d] == enemy)
  132.             ;
  133.             if (b[sq] == friendly)
  134.                 while(b[sq -= d] == enemy)
  135.                    b[sq]=friendly;
  136.           }
  137.       }
  138.       b[move]=friendly;
  139.    }
  140. }
  141. //
  142. //  FUNCTION: score()
  143. //
  144. //  PURPOSE:  Calculate the value of board
  145. //
  146. INT NEAR PASCAL score(
  147. BYTE b[],
  148. BYTE friendly,
  149. BYTE enemy)
  150. {
  151.     INT *pvalue;
  152.     BYTE *pb;
  153.     INT fpoints=0;
  154.     INT epoints=0;
  155.     INT ecount=0;
  156.     BYTE bv;
  157.     INT v,b11,b18,b81,b88;
  158.     static INT value[79] = {     99, -8,  8,  6,  6,  8, -8, 99,000,
  159.                 000, -8,-24, -4, -3, -3, -4,-24, -8,000,
  160.                 000,  8, -4,  7,  4,  4,  7, -4,  8,000,
  161.                 000,  6, -3,  4,  0,  0,  4, -3,  6,000,
  162.                 000,  6, -3,  4,  0,  0,  4, -3,  6,000,
  163.                 000,  8, -4,  7,  4,  4,  7, -4,  8,000,
  164.                 000, -8,-24, -4, -3, -3, -4,-24, -8,000,
  165.                 000, 99, -8,  8,  6,  6,  8, -8, 99,infin};
  166.     static INT value2[79]= {     99, -8,  8,  6,  6,  8, -8, 99,000,
  167.                 000, -8,-24,  0,  1,  1,  0,-24, -8,000,
  168.                 000,  8,  0,  7,  4,  4,  7,  0,  8,000,
  169.                 000,  6,  1,  4,  1,  1,  4,  1,  6,000,
  170.                 000,  6,  1,  4,  1,  1,  4,  1,  6,000,
  171.                 000,  8,  0,  7,  4,  4,  7,  0,  8,000,
  172.                 000, -8,-24,  0,  1,  1,  1,-24, -8,000,
  173.                 000, 99, -8,  8,  6,  6,  8, -8, 99,infin};
  174.     pb = &b[11];
  175.     b11 = *pb;
  176.     b18 = b[18];
  177.     b81 = b[81];
  178.     b88 = b[88];
  179.     if ((b11 != empty) || (b18 != empty) || (b81 != empty) || (b88 != empty)) {
  180.     pvalue = value2;
  181.     if (b11 == empty) {
  182.         value2[12-11] = -8;  value2[21-11] = -8;  value2[22-11] = -24;
  183.     } else {
  184.         value2[12-11] = 12;  value2[21-11] = 12;  value2[22-11] = 8;
  185.     }
  186.     if (b18 == empty) {
  187.         value2[17-11] = -8;  value2[28-11] = -8;  value2[27-11] = -24;
  188.     } else {
  189.         value2[17-11] = 12;  value2[28-11] = 12;  value2[27-11] = 8;
  190.     }
  191.     if (b81 == empty) {
  192.         value2[82-11] = -8;  value2[71-11] = -8;  value2[72-11] = -24;
  193.     } else {
  194.         value2[82-11] = 12;  value2[71-11] = 12;  value2[72-11] = 8;
  195.     }
  196.     if (b88 == empty) {
  197.         value2[87-11] = -8;  value2[78-11] = -8;  value2[77-11] = -24;
  198.     } else {
  199.         value2[87-11] = 12;  value2[78-11] = 12;  value2[77-11] = 8;
  200.     }
  201.     } else {
  202.     pvalue = value;
  203.     }
  204.     while((v=*pvalue++) != infin) {
  205.        bv = *pb++;
  206.        if (bv == friendly)
  207.        fpoints += v;
  208.        else if (bv == enemy) {
  209.            epoints += v;
  210.        ecount++;
  211.        }
  212.     }
  213.     if (!ecount)          // any enemy pieces on the board?
  214.        return(win);       // if not, we just won!
  215.     else
  216.        return(fpoints-epoints);
  217. }
  218. //
  219. //  FUNCTION: minmax()
  220. //
  221. //  PURPOSE:  Play human move then recursively play computer move 
  222. //
  223. INT NEAR PASCAL minmax(
  224. BYTE b[max_depth + 2][100],
  225. INT move,
  226. BYTE friendly,
  227. BYTE enemy,
  228. INT ply,
  229. INT vmin,
  230. INT vmax)
  231. {
  232.     BYTE *pCurrent, *pPrevious, *pSource, *pDest;
  233.     INT *pMoves;
  234.     INT *pBestMove;
  235.     INT i;
  236.     INT sq, value, cur_move;
  237.     INT count=0;    // not used !
  238.     pPrevious = &b[ply][0];
  239.     pCurrent =  &b[ply+1][0];
  240.     pSource = &b[ply][11];
  241.     pDest =   &b[ply+1][11];
  242.     for (i=11 ; i<=88 ; i++) *pDest++=*pSource++;
  243.     pBestMove = &BestMove[ply];
  244.     if (move == PASS) {
  245.         if (ply == depth) {
  246.             pMoves = moves;
  247.             while((sq = *pMoves++) != 0) {
  248.                 if (legalcheck(pCurrent,sq,enemy,friendly))
  249.                     return(score(pCurrent,friendly,enemy));
  250.             }
  251.             return(finalscore(pCurrent,friendly,enemy));
  252.         }
  253.     }
  254.     else {
  255.         if (ply == 0) {
  256.             hDisp = GetDC(hWin);
  257.             paintmove(pCurrent,move,friendly,enemy);
  258.             ReleaseDC(hWin, hDisp);
  259.         }
  260.         else {
  261.             makemove(pCurrent,move,friendly,enemy);
  262.             if (ply == depth) return(score(pCurrent,friendly,enemy));
  263.         }
  264.     }
  265.     pMoves = moves;
  266.     cur_move = PASS;
  267.     *pBestMove = PASS;
  268.     while((sq = *pMoves++) != 0) {
  269.         if (legalcheck(pCurrent,sq,enemy,friendly)) {
  270.            cur_move = sq;
  271.            value = minmax(b,cur_move,enemy,friendly,ply+1,-vmax,-vmin);
  272.            if (value > vmin) {
  273.               vmin = value;
  274.               *pBestMove = cur_move;
  275.               if (value >= vmax) goto cutoff;   // alpha-beta cutoff
  276.            }
  277.         }
  278.     }
  279.     if (cur_move == PASS) {
  280.         if (move == PASS)        // two passes in a row mean game is over
  281.             return(finalscore(pCurrent,friendly,enemy));
  282.         else {
  283.             value = minmax(b,PASS,enemy,friendly,ply+1,-vmax,-vmin);
  284.             if (value > vmin) vmin = value;
  285.         }
  286.     }
  287. cutoff:
  288.     return(-vmin);
  289. }