gen.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /* This file contains the move-generator 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 <stdio.h>
  18. #include "gnuchess.h"
  19. #define pseudolegal(fromval,toval) ((toval == 0) ? NORMAL : ((fromval <= 6 && fromval >= 1 && toval <= 6 && toval >= 1 ? DEFENSE : ((fromval <= 6 && fromval >= 1 && toval < 0) || (fromval < 0 && toval <= 6 && toval >= 1) ? CAPTURE : OFF))))
  20. int attackers[10],defenders[10],natt,ndef;
  21. extern int nmoves,gentype;
  22. extern struct dirtypes pieces[MAXPC+6];
  23. extern int pcval[MAXPC+1];
  24. extern char *pctype[(MAXPC*2)+1];
  25. #define addmove(bd,_from,_to,moves)\
  26. {\
  27. moves[nmoves].from = _from;\
  28. moves[nmoves].to = _to;\
  29. moves[nmoves].movpiece = bd[_from].piece;\
  30. moves[nmoves].flags = 0;\
  31. moves[nmoves].capcount = 0;\
  32. if (bd[_to].piece != 0) {\
  33. moves[nmoves].flags |= CAPFLAG;\
  34. moves[nmoves].cappiece = bd[_to].piece;\
  35. moves[nmoves].capcount = bd[_to].moved; /* Save move count */\
  36. permflag = moves[nmoves].flags;\
  37. }\
  38. switch(bd[_from].piece) {\
  39. case WK : if (_from == 95) switch(_to) {\
  40. case 97 : moves[nmoves].flags |= KCASFLAG;\
  41. break;\
  42. case 93 : moves[nmoves].flags |= QCASFLAG;\
  43. break;\
  44. }\
  45. break;\
  46. case BK : if (_from == 25) switch(_to) {\
  47. case 27 : moves[nmoves].flags |= KCASFLAG;\
  48. break;\
  49. case 23 : moves[nmoves].flags |= QCASFLAG;\
  50. break;\
  51. }\
  52. break;\
  53. case WP : if (_to < 29) {\
  54. for (ii = WQ; ii >= WN; ii--) {\
  55. moves[nmoves].from = _from;\
  56. moves[nmoves].to = _to;\
  57. moves[nmoves].movpiece = WP;\
  58. moves[nmoves].propiece = ii;\
  59. moves[nmoves].cappiece = bd[_to].piece;\
  60. moves[nmoves].flags = permflag;\
  61. moves[nmoves].flags |= PROMFLAG;\
  62. nmoves = nmoves + 1;\
  63. }\
  64. nmoves = nmoves - 1;\
  65. break;\
  66. }\
  67. case BP : if (_to > 90) {\
  68. for (ii = BQ; ii <= BN; ii++) {\
  69. moves[nmoves].from = _from;\
  70. moves[nmoves].to = _to;\
  71. moves[nmoves].movpiece = BP;\
  72. moves[nmoves].propiece = ii;\
  73. moves[nmoves].cappiece = bd[_to].piece;\
  74. moves[nmoves].flags = permflag;\
  75. moves[nmoves].flags |= PROMFLAG;\
  76. nmoves = nmoves + 1;\
  77. }\
  78. nmoves = nmoves - 1;\
  79. break;\
  80. }\
  81. }\
  82. nmoves = nmoves + 1;\
  83. }
  84. /*
  85. * Generate creates a move list given the current board configuration.
  86. * The move list will contain all pseudo-legal moves for the side on
  87. * move.
  88. */
  89. int generate(bd,moves)
  90. register struct bdtype *bd;
  91. register struct mvlist *moves;
  92. {
  93. register ii, i,j,emptsq,incr,movetype,type;
  94. register rank2lo,rank2hi,pwncap1,pwncap2,pwnmov1,pwnmov2,pc,oppcol;
  95. register kingloc,krloc,qrloc,ksdest,qsdest,kingtyp,rooktyp;
  96. char permflag;
  97. nmoves = 0;
  98. if (bd[TOMOVE].moved == WHITE) {
  99. rank2lo = 80; rank2hi = 89; pwncap1 = -9; pwncap2 = -11;
  100. pwnmov1 = -10; pwnmov2 = -20; pc = WP; oppcol = BLACK;
  101. kingloc = 95; krloc = 98; qrloc = 91; ksdest = 97; qsdest = 93;
  102. kingtyp = WK; rooktyp = WR;
  103. } else {
  104. rank2lo = 30; rank2hi = 39; pwncap1 = 9; pwncap2 = 11;
  105. pwnmov1 = 10; pwnmov2 = 20; pc = BP; oppcol = WHITE;
  106. kingloc = 25; krloc = 28; qrloc = 21; ksdest = 27; qsdest = 23;
  107. kingtyp = BK; rooktyp = BR;
  108. }
  109. if (bd[kingloc].piece == kingtyp && bd[krloc].piece == rooktyp &&
  110. bd[kingloc].moved == 0 && bd[krloc].moved == 0 &&
  111. bd[kingloc+1].piece == EMP && bd[krloc-1].piece == EMP &&
  112. !sqattacked(bd,kingloc,oppcol) && !sqattacked(bd,kingloc+1,oppcol) &&
  113. !sqattacked(bd,krloc-1,oppcol))
  114. {
  115. addmove(bd,kingloc,ksdest,moves);
  116. }
  117. if (bd[kingloc].piece == kingtyp && bd[qrloc].piece == rooktyp &&
  118. bd[kingloc].moved == 0 && bd[qrloc].moved == 0 &&
  119. bd[kingloc-1].piece == EMP && bd[qrloc+1].piece == EMP &&
  120. bd[qrloc+2].piece == EMP && !sqattacked(bd,kingloc,oppcol) &&
  121. !sqattacked(bd,kingloc-1,oppcol) && !sqattacked(bd,qrloc+1,oppcol) &&
  122. !sqattacked(bd,qrloc+2,oppcol) && !sqattacked(bd,qrloc+3,oppcol))
  123. {
  124. addmove(bd,kingloc,qsdest,moves);
  125. }
  126. for (i = 21; i <= 98; i++)
  127. if (bd[i].piece == pc) {
  128. if (COLOR(bd[i+pwncap1].piece) == oppcol)
  129. addmove(bd,i,i+pwncap1,moves);
  130. if (COLOR(bd[i+pwncap2].piece) == oppcol)
  131. addmove(bd,i,i+pwncap2,moves);
  132. emptsq = (bd[i+pwnmov1].piece == EMP);
  133. if (emptsq) {
  134. if (i > rank2lo && i < rank2hi && bd[i+pwnmov2].piece == EMP)
  135. addmove(bd,i,i+pwnmov2,moves);
  136. addmove(bd,i,i+pwnmov1,moves);
  137. }
  138. }
  139. else if (COLOR(bd[i].piece) == bd[TOMOVE].moved)
  140. {
  141. type = abs(bd[i].piece);
  142. for (j = 0; j < pieces[type].ndirs; j++)
  143. {
  144. incr = pieces[type].dirs[j];
  145. for (;;) {
  146. movetype = pseudolegal(bd[i].piece,bd[i+incr].piece);
  147. if (movetype == NORMAL || movetype == CAPTURE)
  148. addmove(bd,i,i+incr,moves);
  149. if (!pieces[type].slide || movetype != NORMAL)
  150. break;
  151. incr += pieces[type].dirs[j];
  152. }
  153. }
  154. }
  155. return(nmoves);
  156. }
  157. /*
  158. * sqattacked returned true if the given square on the given board
  159. * is attacked by any piece of the given color.
  160. */
  161. sqattacked(bd,sq,attackcol)
  162. register struct bdtype *bd;
  163. {
  164. int i, j, incr, pc;
  165. /*
  166. printf("Is square %d attacked by color %d\n",sq,attackcol);
  167. */
  168. if (attackcol == WHITE)
  169. {
  170. if (bd[sq+9].piece == WP || bd[sq+11].piece == WP)
  171. return(TRUE);
  172. }
  173. else if (attackcol == BLACK)
  174. {
  175. if (bd[sq-9].piece == BP || bd[sq-11].piece == BP)
  176. return(TRUE);
  177. }
  178. for (i = WN; i <= WK; i++)
  179. {
  180. pc = (attackcol == WHITE) ? i : -i;
  181. for (j = 0; j < pieces[i].ndirs; j++)
  182. {
  183. incr = pieces[i].dirs[j];
  184. for (;;)
  185. {
  186. if (bd[sq+incr].piece == pc)
  187. return(TRUE);
  188. if (!pieces[i].slide || bd[sq+incr].piece != EMP)
  189. break;
  190. incr += pieces[i].dirs[j];
  191. }
  192. }
  193. }
  194. return(FALSE);
  195. }
  196. /*
  197. * showstatic prints a list of the static exchanges that will
  198. * occur on a square during a swapoff of all pieces that attack
  199. * a piece on that square.
  200. */
  201. showstatic(bd,sq)
  202. struct bdtype bd[120];
  203. {
  204. printf("staticexchange at ");
  205. lin_to_alg(sq,stdout);
  206. putchar('\n');
  207. fflush(stdout);
  208. printf(" = %d\n",staticexchange(bd,sq));
  209. }
  210. #define addatt(val) {attackers[natt++] = val;}
  211. #define adddef(val) {defenders[ndef++] = val;}
  212. /*
  213. * showattacks prints a list of the pieces which attack the given
  214. * square on the given board.
  215. */
  216. showattacks(bd,sq)
  217. struct bdtype bd[120];
  218. {
  219. int i, j, incr, pc, gotone,viccol;
  220. natt = ndef = 0;
  221. viccol = COLOR(bd[sq].piece);
  222. for (i = BP+1; i <= WK; i++)
  223. {
  224. for (j = 0; j < pieces[i].ndirs; j++)
  225. {
  226. incr = pieces[i].dirs[j];
  227. for (;;)
  228. {
  229. if (((i == BP+1) && (bd[sq+incr].piece == BP)) ||
  230. ((abs(bd[sq+incr].piece) == i) && (i != BP+1) &&
  231. bd[sq+incr].piece != BP))
  232. {
  233. if (COLOR(bd[sq+incr].piece) == viccol)
  234. adddef(pcval[abs(bd[sq+incr].piece)])
  235. else
  236. addatt(pcval[abs(bd[sq+incr].piece)]);
  237. #ifdef EXCHDEBUG
  238. printf("%s at ",(bd[sq+incr].piece < 0) ?
  239. pctype[abs(bd[sq+incr].piece)-1] :
  240. pctype[bd[sq+incr].piece+6]);
  241. lin_to_alg(sq+incr,stdout);
  242. putchar('\n');
  243. #endif
  244. }
  245. if (!pieces[i].slide || bd[sq+incr].piece != EMP)
  246. break;
  247. incr += pieces[i].dirs[j];
  248. }
  249. }
  250. }
  251. }
  252. /*
  253. * staticexchange actually does a full static exchange on the
  254. * given square, returning a residue representing how much
  255. * material is won or lost.
  256. */
  257. staticexchange(bd,sq)
  258. struct bdtype bd[120];
  259. {
  260. int attindex,defindex,prevresidue,residue,i;
  261. showattacks(bd,sq);
  262. #ifdef EXCHDEBUG
  263. printf("natt = %d, ndef = %d\n",natt,ndef);
  264. for (i = 0; i < natt; i++)
  265. printf("attackers[%d]=%d\n",i,attackers[i]);
  266. for (i = 0; i < ndef; i++)
  267. printf("defenders[%d]=%d\n",i,defenders[i]);
  268. #endif
  269. if (natt == 0) return(0);
  270. else if (ndef == 0) return(pcval[abs(bd[sq].piece)]);
  271. attindex = -1;
  272. defindex = -2;
  273. residue = 0;
  274. for (i = 1;; i++)
  275. {
  276. if (++defindex < ndef)
  277. {
  278. prevresidue = residue;
  279. if (i == 1)
  280. residue += pcval[abs(bd[sq].piece)];
  281. else
  282. residue += defenders[defindex];
  283. if (residue < 0)
  284. {
  285. #ifdef EXCHDEBUG
  286. printf("End Defender = %d, prevresidue = %d, residue = %d\n",
  287. i,prevresidue,residue);
  288. #endif
  289. return(MIN(MAX(prevresidue,0),pcval[abs(bd[sq].piece)]));
  290. }
  291. #ifdef EXCHDEBUG
  292. printf("Defender = %d, prevresidue = %d, residue = %d\n",
  293. i,prevresidue,residue);
  294. #endif
  295. }
  296. else break;
  297. if (++attindex < natt)
  298. {
  299. prevresidue = residue;
  300. residue -= attackers[attindex];
  301. if (residue > pcval[abs(bd[sq].piece)])
  302. {
  303. #ifdef EXCHDEBUG
  304. printf("End Attacker = %d, prevresidue = %d, residue = %d\n",
  305. i,prevresidue,residue);
  306. #endif
  307. return(MIN(MAX(prevresidue,0),pcval[abs(bd[sq].piece)]));
  308. }
  309. #ifdef EXCHDEBUG
  310. printf("Attacker = %d, prevresidue = %d, residue = %d\n",
  311. i,prevresidue,residue);
  312. #endif
  313. }
  314. else break;
  315. }
  316. #ifdef EXCHDEBUG
  317. printf("End Iter, prevresidue = %d, residue = %d\n",
  318. prevresidue,residue);
  319. #endif
  320. return(MIN(MAX(prevresidue,0),pcval[abs(bd[sq].piece)]));
  321. }
  322. /*
  323. * modmat looks at the material value for both sides on the
  324. * given board, and returns a value which, if added to that
  325. * material value, represents the actual material value after
  326. * static exchanges are taken into account.
  327. */
  328. modmat(bd)
  329. struct bdtype bd[120];
  330. {
  331. int i,movemat,movemat2,curmat2,movedmat,curmat;
  332. movemat = movemat2 = curmat2 = movedmat = curmat = 0;
  333. for (i = 21; i <= 98; i++)
  334. if (bd[i].piece != EMP && bd[i].piece != OFF)
  335. {
  336. #ifdef EXCHDEBUG
  337. printf("sq = ");
  338. lin_to_alg(i,stdout);
  339. putchar('\n');
  340. #endif
  341. if (OPPCOLOR(COLOR(bd[i].piece)) == bd[TOMOVE].moved)
  342. {
  343. showattacks(bd,i);
  344. curmat = staticexchange(bd,i);
  345. #ifdef EXCHDEBUG
  346. printf("curmat = %d\n",curmat);
  347. #endif
  348. if (curmat > movedmat)
  349. movedmat = curmat;
  350. }
  351. else if (COLOR(bd[i].piece) == bd[TOMOVE].moved)
  352. {
  353. showattacks(bd,i);
  354. curmat2 = staticexchange(bd,i);
  355. #ifdef EXCHDEBUG
  356. printf("curmat2 = %d\n",curmat2);
  357. #endif
  358. if (curmat2 > movemat)
  359. {
  360. movemat2 = movemat;
  361. movemat = curmat2;
  362. }
  363. else if (curmat2 > movemat2)
  364. movemat2 = curmat2;
  365. }
  366. }
  367. #ifdef EXCHDEBUG
  368. printf("modmat: movedmat = %d, movemat = %d, movemat2 = %d\n",
  369. movedmat,movemat,movemat2);
  370. printf("modmat: movedmat - (.75 * movemat2) = %f\n",
  371. (float)movedmat - (.75 * (float)movemat2));
  372. #endif
  373. return(movedmat - (.75 * movemat2));
  374. }