eval.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /* This file contains static-evaluation routines for CHESS.
  2. Copyright (C) 1986 Free Software Foundation, Inc.
  3. This file is part of CHESS.
  4. CHESS is distributed in the hope that it will be useful,
  5. but WITHOUT ANY WARRANTY. No author or distributor
  6. accepts responsibility to anyone for the consequences of using it
  7. or for whether it serves any particular purpose or works at all,
  8. unless he says so in writing. Refer to the CHESS General Public
  9. License for full details.
  10. Everyone is granted permission to copy, modify and redistribute
  11. CHESS, but only under the conditions described in the
  12. CHESS General Public License. A copy of this license is
  13. supposed to have been given to you along with CHESS so you
  14. can know your rights and responsibilities. It should be in a
  15. file named COPYING. Among other things, the copyright notice
  16. and this notice must be preserved on all copies. */
  17. #include "algdefs.h"
  18. #include "crucialdefs.h"
  19. #include "fixeddefs.h"
  20. #include "externmap.h"
  21. #include "bitmacs.h"
  22. int pcval[NPIECES] = {100,325,350,500,900,0};
  23. int sideval[NCOLORS];
  24. extern char *strpiece[NPIECES];
  25. extern char *sqchar[];
  26. extern unsigned int sqbits[];
  27. extern int okprint;
  28. float evalpawn(color)
  29. {
  30. }
  31. float evalbishop(color)
  32. {
  33. unsigned int temp[2],temp2[2];
  34. register sq;
  35. float score;
  36. score = 0.0;
  37. for (sq = A1; sq <= H8; sq++)
  38. if (MEMBER(sq,pieces[color][BISHOP]))
  39. {
  40. BIT_COPY(attackfr[color][sq],temp);
  41. BIT_NOT(pieces[color][PAWN],temp2);
  42. BIT_AND(temp2,temp);
  43. /* Square control */
  44. /* 2.4 for each square attacked not including friendly pawns - 7 */
  45. /* Development -11 if on back rank */
  46. score += (2.4 * (count_bits(temp) - 7)) +
  47. (MEMBER(sq,rows[color == WHITE ? 0 : 7]) ? -11.0 : 0.0);
  48. }
  49. return(score);
  50. }
  51. float evalrook(color,krow,kcol)
  52. {
  53. register sq,sq2;
  54. float score;
  55. MAP temp[2],temp2[2];
  56. int prow,pcol;
  57. score = 0.0;
  58. for (sq = A1; sq <= H8; sq++)
  59. if (MEMBER(sq,pieces[color][ROOK]))
  60. {
  61. setrowcol(sq,&prow,&pcol);
  62. /* King tropism */
  63. /* -1.6 * minimum of vert/horiz dist from enemy king */
  64. /* Square control */
  65. /* 1.6 for each square attacked */
  66. score += (-1.6 * MIN(ABS(prow-krow),ABS(pcol-kcol))) +
  67. (1.6 * count_bits(attackfr[color][sq]));
  68. /* 8 for each doubled rook */
  69. for (sq2 = A1; sq2 <= H8; sq2++)
  70. if (MEMBER(sq2,attackfr[color][sq]))
  71. if (MEMBER(sq2,pieces[color][ROOK]))
  72. score += 8;
  73. /* 8 for each open file */
  74. BIT_COPY(cols[pcol-1],temp);
  75. BIT_COPY(pieces[color][PAWN],temp2);
  76. BIT_OR(pieces[OPP(color)][PAWN],temp2);
  77. BIT_AND(temp2,temp);
  78. if (!(NOT_ZERO(temp))) score += 8;
  79. /* 22 for being on 7th rank */
  80. score += (MEMBER(sq,rows[color == WHITE ? 7 : 0])) ? 22 : 0;
  81. /* 3 pt. bonus for rook being on semi-open file */
  82. /* (e.g. one with no friendly pawns, at least one enemy pawn */
  83. /* that is not defended by other enemy pawns, and if advanced */
  84. /* would be subject to attack by at least one of our pawns */
  85. }
  86. return(score);
  87. }
  88. float evalqueen(color,krow,kcol)
  89. {
  90. register sq,sq2;
  91. float score;
  92. int prow,pcol;
  93. score = 0.0;
  94. for (sq = A1; sq <= H8; sq++)
  95. if (MEMBER(sq,pieces[color][QUEEN]))
  96. {
  97. setrowcol(sq,&prow,&pcol);
  98. /* King tropism */
  99. /* -0.8 * minimum of vert/horiz distances from enemy king */
  100. score += -0.8 * MIN(ABS(prow-krow),ABS(pcol-kcol));
  101. /* Square control */
  102. /* 0.8 for each square attacked not attacked by enemy */
  103. for (sq2 = A1; sq2 <= H8; sq2++)
  104. if (MEMBER(sq2,attackfr[color][sq]))
  105. if (!(NOT_ZERO(attackto[OPP(color)][sq2])))
  106. score += 0.8;
  107. }
  108. return(score);
  109. }
  110. float evalknight(color,krow,kcol)
  111. {
  112. register sq;
  113. float score;
  114. int prow,pcol;
  115. score = 0.0;
  116. for (sq = A1; sq <= H8; sq++)
  117. if (MEMBER(sq,pieces[color][KNIGHT]))
  118. {
  119. setrowcol(sq,&prow,&pcol);
  120. /* Center tropism, king tropism, development */
  121. score += (1.6 * (6. - (2. * (ABS(4.5 - prow) + ABS(4.5 - pcol))))) +
  122. (1.2 * (5. - (ABS(krow-prow)+ABS(kcol-pcol)))) +
  123. (MEMBER(sq,rows[color == WHITE ? 0 : 7]) ? -9.4 : 0.);
  124. }
  125. return((float)score);
  126. }
  127. eval(show,color,mat,pos)
  128. int show,color;
  129. float *mat,*pos;
  130. {
  131. int npieces[NCOLORS][NPIECES];
  132. MAP temp[2];
  133. register i,j,sidewin,pa,mt,md,sq,kingloc,kingeloc,foundsafesq,nsqattacked;
  134. register nonpenemy,qpresent,importance,rowtouse,psidefiles,psamefile,
  135. nadj;
  136. int krow,kcol,ekrow,ekcol,prow,pcol;
  137. float matadv,ms,kingsafe,notcorner,cramp,noneighbor,noponfles,attacksq,
  138. pawneval,knighteval,bishopeval,rookeval,queeneval,toteval;
  139. okprint = FALSE;
  140. i = j = sidewin = pa = mt = md = sq = kingloc = 0;
  141. kingeloc = foundsafesq = nsqattacked = 0;
  142. nonpenemy = qpresent = importance = rowtouse = 0;
  143. psidefiles = psamefile = nadj = 0;
  144. krow = kcol = ekrow = ekcol = prow = pcol = 0;
  145. matadv = ms = kingsafe = notcorner = cramp = 0.0;
  146. noneighbor = noponfles = attacksq = 0.0;
  147. pawneval = knighteval = bishopeval = rookeval = 0.0;
  148. queeneval = toteval = 0.0;
  149. sideval[WHITE] = 0;
  150. sideval[BLACK] = 0;
  151. for (i = 0; i < NPIECES; i++)
  152. for (j = 0; j < NCOLORS; j++)
  153. {
  154. npieces[j][i] = count_bits(pieces[j][i]);
  155. sideval[j] += npieces[j][i]*pcval[i];
  156. #ifdef PRINT_EVAL
  157. printf("Number of %s %ss = %d\n",
  158. j == WHITE ? "white" : "black",
  159. strpiece[i],
  160. npieces[j][i]);
  161. #endif PRINT_EVAL
  162. }
  163. #ifdef PRINT_EVAL
  164. for (j = 0; j < NCOLORS; j++)
  165. printf("Material for %s = %d\n",
  166. j == WHITE ? "white" : "black",
  167. sideval[j]);
  168. #endif PRINT_EVAL
  169. sidewin = (sideval[WHITE] >= sideval[BLACK] ?
  170. WHITE : BLACK);
  171. #ifdef PRINT_EVAL
  172. printf("Winning side is %s\n",sidewin == WHITE ? "white" : "black");
  173. #endif PRINT_EVAL
  174. md = sideval[sidewin] - sideval[OPP(sidewin)];
  175. pa = npieces[sidewin][PAWN];
  176. mt = sideval[sidewin] + sideval[OPP(sidewin)];
  177. ms = MIN(2400,md) + md*pa*(8000-mt)/(6400*(pa+1));
  178. matadv = MIN(3100,ms);
  179. /* Do king safety */
  180. /* First calculate importance */
  181. nonpenemy = count_bits(side[OPP(color)]) - npieces[OPP(color)][PAWN];
  182. qpresent = npieces[OPP(color)][QUEEN] != 0 ? 2 : 0;
  183. importance = nonpenemy + qpresent - 2;
  184. if (importance <= 0)
  185. {
  186. printf("King safety ignored.\n");
  187. return;
  188. }
  189. /* Now calculate sanctuary term */
  190. BIT_COPY(pieces[color][KING],temp);
  191. BIT_AND(sanctuary,temp);
  192. notcorner = NOT_ZERO(temp) ? 0.0 : 3.1;
  193. /* Now find king location and store its coordinates */
  194. for (sq = A1; sq <= H8; sq++)
  195. if (MEMBER(sq,pieces[color][KING]))
  196. kingloc = sq;
  197. else if (MEMBER(sq,pieces[OPP(color)][KING]))
  198. kingeloc = sq;
  199. setrowcol(kingloc,&krow,&kcol);
  200. setrowcol(kingeloc,&ekrow,&ekcol);
  201. /* Now figure out whether king is cramped */
  202. foundsafesq = FALSE;
  203. if (color == BLACK)
  204. {
  205. BIT_AND(rows[7],temp);
  206. }
  207. else
  208. {
  209. BIT_AND(rows[0],temp);
  210. }
  211. IFMAPNOTZERO(temp)
  212. {
  213. BIT_COPY(kingmvmaps[kingloc],temp);
  214. rowtouse = (color == BLACK) ? 6 : 1;
  215. BIT_AND(rows[rowtouse],temp);
  216. for (sq = A1; sq <= H8; sq++)
  217. if (MEMBER(sq,temp))
  218. if ((attackto[color][sq][LOBD] == 0 &&
  219. attackto[color][sq][HIBD] == 0) ||
  220. !(MEMBER(sq,pieces[color][PAWN])))
  221. {
  222. foundsafesq = TRUE;
  223. break;
  224. }
  225. if (!foundsafesq)
  226. cramp = 0.8;
  227. }
  228. /* Figure out number of adjacent pieces and pawns. */
  229. BIT_COPY(kingmvmaps[kingloc],temp);
  230. BIT_AND(side[color],temp);
  231. nadj = count_bits(temp);
  232. if (nadj == 1) {
  233. printf("Only one pawn/piece next to king.\n");
  234. noneighbor = 1.6;
  235. }
  236. else if (nadj == 0) {
  237. printf("No adjacent pawn/piece next to king.\n");
  238. noneighbor = 3.1;
  239. }
  240. /* Figure out number of open files in front of king. */
  241. BIT_COPY(cols[kingloc % 8],temp);
  242. BIT_AND(pieces[color][PAWN],temp);
  243. psamefile = count_bits(temp);
  244. if (psamefile == 0) {
  245. noponfles = 4.1;
  246. }
  247. if (kingloc % 8 > 0) {
  248. BIT_COPY(cols[(kingloc % 8) - 1],temp);
  249. BIT_AND(pieces[color][PAWN],temp);
  250. psidefiles = count_bits(temp);
  251. }
  252. if (kingloc % 8 < 7) {
  253. BIT_COPY(cols[(kingloc % 8) + 1],temp);
  254. BIT_AND(pieces[color][PAWN],temp);
  255. psidefiles += count_bits(temp);
  256. }
  257. if (psidefiles < 1)
  258. noponfles += 3.6;
  259. /* Now penalize attacked squares adjacent to the king */
  260. /*
  261. printf("The following squares adjacent to the king are attacked: ");
  262. */
  263. BIT_COPY(kingmvmaps[kingloc],temp);
  264. for (sq = A1; sq <= H8; sq++)
  265. if (MEMBER(sq,temp))
  266. if (NOT_ZERO(attackto[OPP(color)][sq]))
  267. {
  268. /*
  269. printf("%s ",sqchar[sq]);
  270. */
  271. nsqattacked++;
  272. }
  273. /*
  274. if (nsqattacked == 0) printf("none");
  275. putchar('\n');
  276. */
  277. if (nsqattacked >= 2)
  278. attacksq = (nsqattacked - 1) * 1.2;
  279. /* Should add king in endgame evaluation stuff here (pp 99 of Frey, 2nd
  280. and 3rd paragraphs from bottom */
  281. /* Finally add up all terms and multiply by importance */
  282. kingsafe = -(importance*(notcorner+cramp+noneighbor+noponfles+attacksq));
  283. /* Still need to add the following. Penalize king by
  284. * 7.8 * (ATPD - 6) where ATPD is the average of the
  285. * taxicab distances of the king to each pawn. The
  286. * taxicab distance is the sum of the rank and file distances
  287. * to the pawn as if the king could move only horizontally or
  288. * vertically. Only when there is a certain small amount
  289. * of material (see Frey).
  290. npawn = 0;
  291. tottaxi = 0;
  292. for (sq = A1; sq <= H8; sq++)
  293. if (MEMBER(sq,pieces[color][PAWN]) ||
  294. MEMBER(sq,pieces[OPP(color)][PAWN]))
  295. {
  296. setrowcol(sq,&prow,&pcol);
  297. tottaxi = prow + pcol;
  298. npawn++
  299. }
  300. score -= 7.8*((tottaxi/npawn) - 6);
  301. */
  302. pawneval = evalpawn(color);
  303. knighteval = evalknight(color,ekrow,ekcol);
  304. bishopeval = evalbishop(color);
  305. rookeval = evalrook(color,ekrow,ekcol);
  306. queeneval = evalqueen(color,ekrow,ekcol);
  307. matadv = (sidewin == color) ? matadv : -matadv;
  308. *mat = matadv;
  309. *pos = kingsafe+pawneval+knighteval+bishopeval+rookeval+queeneval;
  310. if (show)
  311. {
  312. printf("Total evaluation for %s = \n",
  313. color == WHITE ? "white":"black");
  314. printf("Material(%.2f) + KingSafety(%.2f) + Pawns(%.2f) + Knights(%.2f) +\n\tBishops(%.2f) + Rooks(%.2f) + Queens(%.2f)\n",
  315. matadv,kingsafe,pawneval,knighteval,bishopeval,rookeval,
  316. queeneval);
  317. }
  318. }
  319. evalpos(show,tomove,mat,pos)
  320. {
  321. float mat,pos;
  322. float evaldiff;
  323. eval(show,OPP(tomove),&mat,&pos);
  324. evaldiff = (-1)*pos;
  325. eval(show,tomove,&mat,&pos);
  326. evaldiff += mat + pos;
  327. if (evaldiff == 0.0)
  328. printf("Position is even.\n");
  329. else
  330. printf("%s is %s %5.2f pawns\n",
  331. tomove == WHITE ? "white":"black",
  332. evaldiff > 0.0 ? "ahead":"behind",
  333. ABS(evaldiff/100.0));
  334. }