Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
7.4 KiB

  1. #include <windows.h>
  2. #include <port1632.h>
  3. #include <process.h>
  4. #include <stdlib.h>
  5. #include "reversi.h"
  6. VOID NEAR PASCAL paintmove(BYTE b[BoardSize], INT move, INT friendly,
  7. INT enemy);
  8. BOOL NEAR PASCAL msgcheck(VOID);
  9. extern INT moves[61];
  10. extern INT BestMove[max_depth+2];
  11. extern HWND hWin;
  12. extern HDC hDisp;
  13. extern INT depth;
  14. extern INT direc[];
  15. /* Indexes for computing scores and whether or not a player has */
  16. /* any pieces on the board. Very order dependant. */
  17. BYTE PieceFlags[] = { 0x00 , /* Ignore sides */
  18. 0x00 , /* Ignore blanks */
  19. 0x01 , /* Human has a piece */
  20. 0x02 , /* Computer has a piece */
  21. };
  22. INT Scores[] = { 0, 0 };
  23. INT humanScore = 0;
  24. INT compScroe = 0;
  25. BYTE FinalComp[] = {0, 0, -1, 1 }; /* Table for compute # computer pieces */
  26. BYTE FinalHuman[] = {0, 0, 1, -1}; /* Table for compute # human pieces */
  27. /*
  28. * The scoring tables are used to evaluate the board
  29. * position. The corners of the board change value
  30. * according to whether a given square is occupied or
  31. * not. This can be done dynamically, saving ~ 1K
  32. * worth of data space but costing an as of yet
  33. * undetermined performance hit.
  34. */
  35. #define B11 11 /* Offsets to particular squares */
  36. #define B18 18
  37. #define B81 81
  38. #define B88 88
  39. #define maskb11 0x08 /* Masks used for indexing into Scoring tables. */
  40. #define maskb18 0x04
  41. #define maskb81 0x02
  42. #define maskb88 0x01
  43. INT NEAR PASCAL finalscore(
  44. BYTE b[],
  45. BYTE friendly,
  46. BYTE enemy)
  47. {
  48. INT i;
  49. INT count=0;
  50. for (i=11 ; i<=88 ; i++) {
  51. if (b[i] == friendly) count++;
  52. else if (b[i] == enemy) count--;
  53. }
  54. if (count > 0)
  55. return(win + count);
  56. else if (count < 0)
  57. return(loss + count);
  58. else
  59. return(0);
  60. }
  61. INT NEAR PASCAL legalcheck(
  62. BYTE b[],
  63. INT move,
  64. BYTE friendly,
  65. BYTE enemy)
  66. {
  67. INT sq,d;
  68. INT *p;
  69. if (b[move] == empty) {
  70. p=direc;
  71. while ((d = *p++) != 0) {
  72. sq=move;
  73. if (b[sq += d] == enemy) {
  74. while(b[sq += d] == enemy)
  75. ;
  76. if (b[sq] == friendly) return(1);
  77. }
  78. }
  79. }
  80. return(0);
  81. }
  82. VOID NEAR PASCAL makemove(
  83. BYTE b[],
  84. INT move,
  85. BYTE friendly,
  86. BYTE enemy)
  87. {
  88. INT sq,d;
  89. INT *p;
  90. if (move != PASS) {
  91. p=direc;
  92. while ((d = *p++) != 0) {
  93. sq=move;
  94. if (b[sq += d] == enemy) {
  95. while(b[sq += d] == enemy)
  96. ;
  97. if (b[sq] == friendly)
  98. while(b[sq -= d] == enemy)
  99. b[sq]=friendly;
  100. }
  101. }
  102. b[move]=friendly;
  103. }
  104. }
  105. /*
  106. calculate the value of board
  107. */
  108. INT NEAR PASCAL score(
  109. BYTE b[],
  110. BYTE friendly,
  111. BYTE enemy)
  112. {
  113. INT *pvalue;
  114. BYTE *pb;
  115. INT fpoints=0;
  116. INT epoints=0;
  117. INT ecount=0;
  118. BYTE bv;
  119. INT v,b11,b18,b81,b88;
  120. static INT value[79] = { 99, -8, 8, 6, 6, 8, -8, 99,000,
  121. 000, -8,-24, -4, -3, -3, -4,-24, -8,000,
  122. 000, 8, -4, 7, 4, 4, 7, -4, 8,000,
  123. 000, 6, -3, 4, 0, 0, 4, -3, 6,000,
  124. 000, 6, -3, 4, 0, 0, 4, -3, 6,000,
  125. 000, 8, -4, 7, 4, 4, 7, -4, 8,000,
  126. 000, -8,-24, -4, -3, -3, -4,-24, -8,000,
  127. 000, 99, -8, 8, 6, 6, 8, -8, 99,infin};
  128. static INT value2[79]= { 99, -8, 8, 6, 6, 8, -8, 99,000,
  129. 000, -8,-24, 0, 1, 1, 0,-24, -8,000,
  130. 000, 8, 0, 7, 4, 4, 7, 0, 8,000,
  131. 000, 6, 1, 4, 1, 1, 4, 1, 6,000,
  132. 000, 6, 1, 4, 1, 1, 4, 1, 6,000,
  133. 000, 8, 0, 7, 4, 4, 7, 0, 8,000,
  134. 000, -8,-24, 0, 1, 1, 1,-24, -8,000,
  135. 000, 99, -8, 8, 6, 6, 8, -8, 99,infin};
  136. pb = &b[11];
  137. b11 = *pb;
  138. b18 = b[18];
  139. b81 = b[81];
  140. b88 = b[88];
  141. if ((b11 != empty) || (b18 != empty) || (b81 != empty) || (b88 != empty)) {
  142. pvalue = value2;
  143. if (b11 == empty) {
  144. value2[12-11] = -8; value2[21-11] = -8; value2[22-11] = -24;
  145. } else {
  146. value2[12-11] = 12; value2[21-11] = 12; value2[22-11] = 8;
  147. }
  148. if (b18 == empty) {
  149. value2[17-11] = -8; value2[28-11] = -8; value2[27-11] = -24;
  150. } else {
  151. value2[17-11] = 12; value2[28-11] = 12; value2[27-11] = 8;
  152. }
  153. if (b81 == empty) {
  154. value2[82-11] = -8; value2[71-11] = -8; value2[72-11] = -24;
  155. } else {
  156. value2[82-11] = 12; value2[71-11] = 12; value2[72-11] = 8;
  157. }
  158. if (b88 == empty) {
  159. value2[87-11] = -8; value2[78-11] = -8; value2[77-11] = -24;
  160. } else {
  161. value2[87-11] = 12; value2[78-11] = 12; value2[77-11] = 8;
  162. }
  163. } else {
  164. pvalue = value;
  165. }
  166. while((v=*pvalue++) != infin) {
  167. bv = *pb++;
  168. if (bv == friendly)
  169. fpoints += v;
  170. else if (bv == enemy) {
  171. epoints += v;
  172. ecount++;
  173. }
  174. }
  175. if (!ecount) /* any enemy pieces on the board? */
  176. return(win); /* if not, we just won! */
  177. else
  178. return(fpoints-epoints);
  179. }
  180. INT NEAR PASCAL minmax(
  181. BYTE b[max_depth + 2][100],
  182. INT move,
  183. BYTE friendly,
  184. BYTE enemy,
  185. INT ply,
  186. INT vmin,
  187. INT vmax)
  188. {
  189. BYTE *pCurrent, *pPrevious, *pSource, *pDest;
  190. INT *pMoves;
  191. INT *pBestMove;
  192. INT i;
  193. INT sq, value, cur_move;
  194. pPrevious = &b[ply][0];
  195. pCurrent = &b[ply+1][0];
  196. pSource = &b[ply][11];
  197. pDest = &b[ply+1][11];
  198. for (i=11 ; i<=88 ; i++) *pDest++=*pSource++;
  199. pBestMove = &BestMove[ply];
  200. if (move == PASS) {
  201. if (ply == depth) {
  202. pMoves = moves;
  203. while((sq = *pMoves++) != 0) {
  204. if (legalcheck(pCurrent,sq,enemy,friendly))
  205. return(score(pCurrent,friendly,enemy));
  206. }
  207. return(finalscore(pCurrent,friendly,enemy));
  208. }
  209. }
  210. else {
  211. if (ply == 0) {
  212. hDisp = GetDC(hWin);
  213. paintmove(pCurrent,move,friendly,enemy);
  214. ReleaseDC(hWin, hDisp);
  215. }
  216. else {
  217. makemove(pCurrent,move,friendly,enemy);
  218. if (ply == depth) return(score(pCurrent,friendly,enemy));
  219. }
  220. }
  221. pMoves = moves;
  222. cur_move = PASS;
  223. *pBestMove = PASS;
  224. while((sq = *pMoves++) != 0) {
  225. if (legalcheck(pCurrent,sq,enemy,friendly)) {
  226. cur_move = sq;
  227. value = minmax(b,cur_move,enemy,friendly,ply+1,-vmax,-vmin);
  228. if (value > vmin) {
  229. vmin = value;
  230. *pBestMove = cur_move;
  231. if (value >= vmax) goto cutoff; /* alpha-beta cutoff */
  232. }
  233. }
  234. }
  235. if (cur_move == PASS) {
  236. if (move == PASS) /* two passes in a row mean game is over */
  237. return(finalscore(pCurrent,friendly,enemy));
  238. else {
  239. value = minmax(b,PASS,enemy,friendly,ply+1,-vmax,-vmin);
  240. if (value > vmin) vmin = value;
  241. }
  242. }
  243. cutoff:
  244. return(-vmin);
  245. }