Leaked source code of windows server 2003
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.

301 lines
7.9 KiB

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