moves.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /* This file contains additional move 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 <stdio.h>
  18. #include "gnuchess.h"
  19. extern int histtot,nmoves;
  20. extern int pcval[MAXPC+1];
  21. extern long hashval;
  22. extern long rands[(2*MAXPC)+1][120];
  23. extern struct mvlist game[MAXGAME];
  24. extern struct gmlist history[MAXGAME];
  25. extern int sqcontrol[120];
  26. extern int cent[MAXPC+1];
  27. struct mvlist save;
  28. /*
  29. * casrook castles or uncastles a rook from the given square to
  30. * the given square depending on whether undo is true or false.
  31. */
  32. casrook(bd,fromsq,tosq,undo)
  33. struct bdtype bd[120];
  34. int fromsq,tosq,undo;
  35. {
  36. #ifdef TREEPOS
  37. if (bd[fromsq].piece > 0)
  38. {
  39. if (!undo)
  40. bd[WPOS].moved += ((sqcontrol[tosq]*cent[abs(bd[tosq].piece)]) -
  41. sqcontrol[fromsq]*cent[abs(bd[fromsq].piece)]);
  42. else
  43. bd[WPOS].moved += ((sqcontrol[fromsq]*cent[abs(bd[fromsq].piece)]) -
  44. sqcontrol[tosq]*cent[abs(bd[tosq].piece)]);
  45. }
  46. else {
  47. if (!undo)
  48. bd[BPOS].moved += ((sqcontrol[tosq]*cent[abs(bd[tosq].piece)]) -
  49. sqcontrol[fromsq]*cent[abs(bd[fromsq].piece)]);
  50. else
  51. bd[BPOS].moved += ((sqcontrol[fromsq]*cent[abs(bd[fromsq].piece)]) -
  52. sqcontrol[tosq]*cent[abs(bd[tosq].piece)]);
  53. }
  54. #endif TREEPOS
  55. bd[tosq].piece = bd[fromsq].piece;
  56. bd[tosq].moved = bd[fromsq].moved + ((undo == TRUE) ? -1 : 1);
  57. bd[fromsq].piece = 0;
  58. bd[fromsq].moved = 0;
  59. }
  60. /*
  61. * addmove adds the given move characterized by the from/to pair
  62. * to a move list given the current board on which the move is
  63. * pseudo-legal.
  64. */
  65. addmove(bd,from,to,moves)
  66. struct bdtype bd[120];
  67. int from, to;
  68. struct mvlist moves[MAXMOVES];
  69. {
  70. register i;
  71. char permflag;
  72. moves[nmoves].from = from;
  73. moves[nmoves].to = to;
  74. moves[nmoves].movpiece = bd[from].piece;
  75. moves[nmoves].flags = 0;
  76. moves[nmoves].capcount = 0;
  77. if (bd[to].piece != 0) {
  78. moves[nmoves].flags |= CAPFLAG;
  79. moves[nmoves].cappiece = bd[to].piece;
  80. moves[nmoves].capcount = bd[to].moved; /* Save move count */
  81. permflag = moves[nmoves].flags;
  82. }
  83. switch(bd[from].piece) {
  84. case WK : if (from == 95) switch(to) {
  85. case 97 : moves[nmoves].flags |= KCASFLAG;
  86. break;
  87. case 93 : moves[nmoves].flags |= QCASFLAG;
  88. break;
  89. }
  90. break;
  91. case BK : if (from == 25) switch(to) {
  92. case 27 : moves[nmoves].flags |= KCASFLAG;
  93. break;
  94. case 23 : moves[nmoves].flags |= QCASFLAG;
  95. break;
  96. }
  97. break;
  98. case WP : if (to < 29) {
  99. for (i = WQ; i >= WN; i--) {
  100. moves[nmoves].from = from;
  101. moves[nmoves].to = to;
  102. moves[nmoves].movpiece = WP;
  103. moves[nmoves].propiece = i;
  104. moves[nmoves].cappiece = bd[to].piece;
  105. moves[nmoves].flags = permflag;
  106. moves[nmoves].flags |= PROMFLAG;
  107. nmoves = nmoves + 1;
  108. }
  109. nmoves = nmoves - 1;
  110. break;
  111. }
  112. case BP : if (to > 90) {
  113. for (i = BQ; i <= BN; i++) {
  114. moves[nmoves].from = from;
  115. moves[nmoves].to = to;
  116. moves[nmoves].movpiece = BP;
  117. moves[nmoves].propiece = i;
  118. moves[nmoves].cappiece = bd[to].piece;
  119. moves[nmoves].flags = permflag;
  120. moves[nmoves].flags |= PROMFLAG;
  121. nmoves = nmoves + 1;
  122. }
  123. nmoves = nmoves - 1;
  124. break;
  125. }
  126. }
  127. nmoves = nmoves + 1;
  128. }
  129. /*
  130. * recordmove records a given move with associated statistics in
  131. * the game history array.
  132. */
  133. recordmove(move,depth,nodes,score,cpu,rate,coltomove)
  134. struct mvlist move;
  135. float cpu,rate;
  136. int coltomove,depth,nodes,score;
  137. {
  138. if (coltomove)
  139. {
  140. histtot++;
  141. history[histtot].wmove.from = move.from;
  142. history[histtot].wmove.to = move.to;
  143. history[histtot].wmove.movpiece = move.movpiece;
  144. history[histtot].wmove.cappiece = move.cappiece;
  145. history[histtot].wmove.capcount = move.capcount;
  146. history[histtot].wmove.propiece = move.propiece;
  147. history[histtot].wmove.flags = move.flags;
  148. if (depth > 0)
  149. {
  150. history[histtot].depth = depth;
  151. history[histtot].nodes = nodes;
  152. history[histtot].score = score;
  153. history[histtot].cpu = cpu;
  154. history[histtot].rate = rate;
  155. }
  156. }
  157. else {
  158. history[histtot].bmove.from = move.from;
  159. history[histtot].bmove.to = move.to;
  160. history[histtot].bmove.movpiece = move.movpiece;
  161. history[histtot].bmove.cappiece = move.cappiece;
  162. history[histtot].bmove.capcount = move.capcount;
  163. history[histtot].bmove.propiece = move.propiece;
  164. history[histtot].bmove.flags = move.flags;
  165. if (depth > 0)
  166. {
  167. history[histtot].depth = depth;
  168. history[histtot].nodes = nodes;
  169. history[histtot].score = score;
  170. history[histtot].cpu = cpu;
  171. history[histtot].rate = rate;
  172. }
  173. }
  174. }
  175. /*
  176. * savemove saves the move indexed by index into a moves list in
  177. * a canonical place.
  178. */
  179. savemove(moves,index)
  180. struct mvlist moves[MAXMOVES];
  181. int index;
  182. {
  183. save.from = moves[index].from;
  184. save.to = moves[index].to;
  185. save.movpiece = moves[index].movpiece;
  186. save.cappiece = moves[index].cappiece;
  187. save.propiece = moves[index].propiece;
  188. save.flags = moves[index].flags;
  189. }
  190. /*
  191. * makemove makes a given move on the given board
  192. */
  193. makemove(moves,bd)
  194. struct mvlist moves;
  195. struct bdtype bd[120];
  196. {
  197. int fromsq,tosq,movpiece,cappiece,propiece;
  198. char flags;
  199. fromsq = moves.from;
  200. tosq = moves.to;
  201. bd[tosq].moved = bd[fromsq].moved + 1; /* increment move count */
  202. bd[fromsq].moved = 0;
  203. movpiece = moves.movpiece;
  204. cappiece = moves.cappiece;
  205. propiece = moves.propiece;
  206. flags = moves.flags;
  207. hashval ^= rands[movpiece+6][fromsq];
  208. hashval ^= rands[movpiece+6][tosq];
  209. bd[fromsq].piece = 0;
  210. bd[tosq].piece = movpiece;
  211. bd[TOMOVE].moved = OPPCOLOR(bd[TOMOVE].moved);
  212. if (movpiece == WK)
  213. bd[WKING].moved = tosq;
  214. else if (movpiece == BK)
  215. bd[BKING].moved = tosq;
  216. #ifdef TREEPOS
  217. if (movpiece > 0)
  218. bd[WPOS].moved += ((sqcontrol[tosq]*cent[abs(movpiece)]) -
  219. sqcontrol[fromsq]*cent[abs(movpiece)]);
  220. else
  221. bd[BPOS].moved += ((sqcontrol[tosq]*cent[abs(movpiece)]) -
  222. sqcontrol[fromsq]*cent[abs(movpiece)]);
  223. #endif TREEPOS
  224. if (flags & CAPFLAG) /* update material balance */
  225. if (movpiece > 0)
  226. {
  227. bd[BMAT].moved -= pcval[abs(cappiece)];
  228. #ifdef TREEPOS
  229. bd[BPOS].moved -= (sqcontrol[tosq]*cent[abs(cappiece)]);
  230. #endif TREEPOS
  231. }
  232. else {
  233. bd[WMAT].moved -= pcval[cappiece];
  234. #ifdef TREEPOS
  235. bd[WPOS].moved -= (sqcontrol[tosq]*cent[abs(cappiece)]);
  236. #endif TREEPOS
  237. }
  238. if (flags & PROMFLAG)
  239. {
  240. bd[tosq].piece = propiece;
  241. if (movpiece > 0)
  242. {
  243. bd[WMAT].moved += (pcval[propiece] - pcval[0]);
  244. #ifdef TREEPOS
  245. bd[WPOS].moved += ((sqcontrol[tosq]*cent[abs(propiece)]) -
  246. sqcontrol[fromsq]*cent[abs(movpiece)]);
  247. #endif TREEPOS
  248. }
  249. else {
  250. bd[BMAT].moved += (pcval[abs(propiece)] - pcval[0]);
  251. #ifdef TREEPOS
  252. bd[BPOS].moved += ((sqcontrol[tosq]*cent[abs(propiece)]) -
  253. sqcontrol[fromsq]*cent[abs(movpiece)]);
  254. #endif TREEPOS
  255. }
  256. }
  257. if (flags & (KCASFLAG | QCASFLAG))
  258. if (movpiece > 0) {
  259. if (flags & KCASFLAG)
  260. casrook(bd,98,96,FALSE);
  261. else if (flags & QCASFLAG)
  262. casrook(bd,91,94,FALSE);
  263. }
  264. else {
  265. if (flags & KCASFLAG)
  266. casrook(bd,28,26,FALSE);
  267. else if (flags & QCASFLAG)
  268. casrook(bd,21,24,FALSE);
  269. }
  270. }
  271. /*
  272. * unmakemove unmakes a given move on the given board
  273. */
  274. unmakemove(moves,bd)
  275. struct mvlist moves;
  276. struct bdtype bd[120];
  277. {
  278. int fromsq, tosq, movpiece, cappiece, propiece;
  279. char flags;
  280. fromsq = moves.from;
  281. tosq = moves.to;
  282. movpiece = moves.movpiece;
  283. cappiece = moves.cappiece;
  284. propiece = moves.propiece;
  285. flags = moves.flags;
  286. hashval ^= rands[movpiece+6][tosq];
  287. hashval ^= rands[movpiece+6][fromsq];
  288. bd[tosq].piece = 0;
  289. bd[fromsq].piece = movpiece;
  290. bd[fromsq].moved = bd[tosq].moved - 1;
  291. bd[tosq].moved = 0;
  292. #ifdef TREEPOS
  293. if (movpiece > 0)
  294. bd[WPOS].moved += ((sqcontrol[fromsq]*cent[abs(movpiece)]) -
  295. sqcontrol[tosq]*cent[abs(movpiece)]);
  296. else
  297. bd[BPOS].moved += ((sqcontrol[fromsq]*cent[abs(movpiece)]) -
  298. sqcontrol[tosq]*cent[abs(movpiece)]);
  299. #endif TREEPOS
  300. if (flags & CAPFLAG) {
  301. bd[tosq].moved = moves.capcount;
  302. if (movpiece > 0)
  303. {
  304. bd[BMAT].moved += pcval[abs(cappiece)];
  305. #ifdef TREEPOS
  306. bd[BPOS].moved += (sqcontrol[tosq]*cent[abs(cappiece)]);
  307. #endif TREEPOS
  308. }
  309. else {
  310. bd[WMAT].moved += pcval[cappiece];
  311. #ifdef TREEPOS
  312. bd[WPOS].moved += (sqcontrol[tosq]*cent[abs(cappiece)]);
  313. #endif TREEPOS
  314. }
  315. bd[tosq].piece = cappiece;
  316. }
  317. if (flags & PROMFLAG)
  318. {
  319. if (movpiece > 0)
  320. {
  321. bd[WMAT].moved -= (pcval[propiece] - pcval[0]);
  322. #ifdef TREEPOS
  323. bd[WPOS].moved += ((sqcontrol[fromsq]*cent[abs(movpiece)]) -
  324. sqcontrol[tosq]*cent[abs(propiece)]);
  325. #endif TREEPOS
  326. }
  327. else {
  328. bd[BMAT].moved -= (pcval[abs(propiece)] - pcval[0]);
  329. #ifdef TREEPOS
  330. bd[BPOS].moved += ((sqcontrol[fromsq]*cent[abs(movpiece)]) -
  331. sqcontrol[tosq]*cent[abs(propiece)]);
  332. #endif TREEPOS
  333. }
  334. }
  335. if (flags & (KCASFLAG|QCASFLAG))
  336. if (movpiece > 0) {
  337. if (flags & KCASFLAG)
  338. casrook(bd,96,98,TRUE);
  339. else if (flags & QCASFLAG)
  340. casrook(bd,94,91,TRUE);
  341. }
  342. else {
  343. if (flags & KCASFLAG)
  344. casrook(bd,26,28,TRUE);
  345. else if (flags & QCASFLAG)
  346. casrook(bd,24,21,TRUE);
  347. }
  348. bd[TOMOVE].moved = OPPCOLOR(bd[TOMOVE].moved);
  349. }
  350. /*
  351. * movem accepts a string which may represent a move and then
  352. * tries to either make that move on the given board or unmake depending
  353. * on undo. It returns true if was able to do something constructive,
  354. * otherwise false.
  355. */
  356. int movem(moves,cmd,undo,bd)
  357. struct mvlist moves[MAXMOVES];
  358. char *cmd;
  359. int undo;
  360. struct bdtype bd[120];
  361. {
  362. char frsq[2],tosq[2];
  363. int nfrsq,ntosq,index,whitomove;
  364. if (undo == FALSE) {
  365. generate(bd,moves);
  366. strncpy(frsq,cmd,2);
  367. strncpy(tosq,&cmd[2],2);
  368. nfrsq = alg_to_lin(frsq);
  369. ntosq = alg_to_lin(tosq);
  370. index = searchlist(nfrsq,ntosq,moves,nmoves);
  371. if (index == NOMATCH)
  372. {
  373. printf("Illegal move\n");
  374. return(FALSE);
  375. }
  376. else {
  377. if (bd[TOMOVE].moved == WHITE)
  378. whitomove = TRUE;
  379. else
  380. whitomove = FALSE;
  381. recordmove(moves[index],0,0,0,0.0,0.0,whitomove);
  382. makemove(moves[index],bd);
  383. return(TRUE);
  384. }
  385. }
  386. else {
  387. if (histtot > 0) {
  388. if (bd[TOMOVE].moved == BLACK)
  389. {
  390. unmakemove(history[histtot].wmove,bd);
  391. histtot--;
  392. }
  393. else
  394. {
  395. unmakemove(history[histtot].bmove,bd);
  396. history[histtot].bmove.from = NULL;
  397. }
  398. }
  399. return(TRUE);
  400. }
  401. }