home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume13 / gnuchess4 / part04 < prev    next >
Internet Message Format  |  1992-08-03  |  56KB

  1. Path: uunet!zephyr.ens.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v13i092:  gnuchess4 - GNU Chess 4.0, Part04/12
  5. Message-ID: <3059@master.CNA.TEK.COM>
  6. Date: 19 Jun 92 15:54:02 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2191
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: cracraft@rice-chex.ai.mit.edu (Stuart Cracraft)
  12. Posting-number: Volume 13, Issue 92
  13. Archive-name: gnuchess4/Part04
  14. Supersedes: gnuchess2: Volume 4, Issue 37-40
  15. Environment: 
  16.  
  17.  
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of archive 4 (of 12)."
  26. # Contents:  src/checkgame.c src/search.c
  27. # Wrapped by billr@saab on Fri Jun 19 08:36:00 1992
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'src/checkgame.c' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'src/checkgame.c'\"
  31. else
  32. echo shar: Extracting \"'src/checkgame.c'\" \(18324 characters\)
  33. sed "s/^X//" >'src/checkgame.c' <<'END_OF_FILE'
  34. X/*
  35. X * checkgame.c - check a chess.lst file for illegal moves
  36. X *
  37. X * Usage: checkgame filename
  38. X *
  39. X * Copyright (c) 1992 Free Software Foundation
  40. X *
  41. X * This file is part of GNU CHESS.
  42. X *
  43. X * GNU Chess is free software; you can redistribute it and/or modify
  44. X * it under the terms of the GNU General Public License as published by
  45. X * the Free Software Foundation; either version 2, or (at your option)
  46. X * any later version.
  47. X *
  48. X * GNU Chess is distributed in the hope that it will be useful,
  49. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  50. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  51. X * GNU General Public License for more details.
  52. X *
  53. X * You should have received a copy of the GNU General Public License
  54. X * along with GNU Chess; see the file COPYING.  If not, write to
  55. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  56. X */
  57. X#include <stdio.h>
  58. X#include "gnuchess.h"
  59. X#ifdef MSDOS
  60. X#include <stdlib.h>
  61. X#include <string.h>
  62. X#include <time.h>
  63. X#define RWA_ACC "r+b"
  64. X#define WA_ACC "w+b"
  65. X#else
  66. X#define RWA_ACC "r+"
  67. X#define WA_ACC "w+"
  68. X#include <sys/param.h>
  69. X#include <sys/types.h>
  70. X#include <sys/times.h>
  71. X#endif /* MSDOS */
  72. XFILE *fd;
  73. X
  74. X#define truescore 0x0001
  75. X#define lowerbound 0x0002
  76. X#define upperbound 0x0004
  77. X#define kingcastle 0x0008
  78. X#define queencastle 0x0010
  79. Xconst short otherside[3] =
  80. X{black, white, neutral};
  81. X
  82. Xstruct GameRec GameList[512];
  83. Xchar mvstr[4][6];
  84. Xlong i, j;
  85. Xshort int ep;
  86. Xint r, c;
  87. Xchar line[128];
  88. Xchar *l;
  89. Xshort int board[64];
  90. Xshort int color[64];
  91. Xshort int GameCnt;
  92. Xint from, to;
  93. Xchar *InPtr;
  94. Xint ckcastld[2];
  95. Xshort int epsquare = -1;
  96. Xint ok;
  97. Xint mvptr = 0;
  98. Xstruct leaf Tree[256];
  99. X
  100. X/* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
  101. X
  102. Xconst short kingP[3] =
  103. X{4, 60, 0};
  104. Xconst short Stboard[64] =
  105. X{rook, knight, bishop, queen, king, bishop, knight, rook,
  106. X pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  107. X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  108. X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  109. X pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  110. X rook, knight, bishop, queen, king, bishop, knight, rook};
  111. Xconst short Stcolor[64] =
  112. X{white, white, white, white, white, white, white, white,
  113. X white, white, white, white, white, white, white, white,
  114. X neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
  115. X neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
  116. X neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
  117. X neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
  118. X black, black, black, black, black, black, black, black,
  119. X black, black, black, black, black, black, black, black};
  120. Xshort board[64], color[64];
  121. X
  122. X/*
  123. X * nextpos[piece][from-square] , nextdir[piece][from-square] gives vector of
  124. X * positions reachable from from-square in ppos with piece such that the
  125. X * sequence    ppos = nextpos[piece][from-square]; pdir =
  126. X * nextdir[piece][from-square]; u = ppos[sq]; do { u = ppos[u]; if(color[u]
  127. X * != neutral) u = pdir[u]; } while (sq != u); will generate the sequence of
  128. X * all squares reachable from sq.
  129. X *
  130. X * If the path is blocked u = pdir[sq] will generate the continuation of the
  131. X * sequence in other directions.
  132. X */
  133. X
  134. Xunsigned char nextpos[8][64][64];
  135. Xunsigned char nextdir[8][64][64];
  136. X
  137. X/*
  138. X * ptype is used to separate white and black pawns, like this; ptyp =
  139. X * ptype[side][piece] piece can be used directly in nextpos/nextdir when
  140. X * generating moves for pieces that are not black pawns.
  141. X */
  142. Xconst short ptype[2][8] =
  143. X{
  144. X  no_piece, pawn, knight, bishop, rook, queen, king, no_piece,
  145. X  no_piece, bpawn, knight, bishop, rook, queen, king, no_piece};
  146. X
  147. X/* data used to generate nextpos/nextdir */
  148. Xstatic const short direc[8][8] =
  149. X{
  150. X  0, 0, 0, 0, 0, 0, 0, 0,
  151. X  10, 9, 11, 0, 0, 0, 0, 0,
  152. X  8, -8, 12, -12, 19, -19, 21, -21,
  153. X  9, 11, -9, -11, 0, 0, 0, 0,
  154. X  1, 10, -1, -10, 0, 0, 0, 0,
  155. X  1, 10, -1, -10, 9, 11, -9, -11,
  156. X  1, 10, -1, -10, 9, 11, -9, -11,
  157. X  -10, -9, -11, 0, 0, 0, 0, 0};
  158. Xstatic const short max_steps[8] =
  159. X{0, 2, 1, 7, 7, 7, 1, 2};
  160. Xstatic const short nunmap[120] =
  161. X{
  162. X  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  163. X  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  164. X  -1, 0, 1, 2, 3, 4, 5, 6, 7, -1,
  165. X  -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
  166. X  -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
  167. X  -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
  168. X  -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
  169. X  -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
  170. X  -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
  171. X  -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
  172. X  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  173. X  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
  174. X
  175. Xint InitFlag = false;
  176. X
  177. X
  178. Xvoid
  179. XDISP (void)
  180. X{
  181. X
  182. X  short r, c, l;
  183. X
  184. X  if (true)
  185. X    {
  186. X      printf ("\n");
  187. X      for (r = 7; r >= 0; r--)
  188. X    {
  189. X      for (c = 0; c <= 7; c++)
  190. X        {
  191. X          l = locn (r, c);
  192. X          if (color[l] == neutral)
  193. X        printf (" -");
  194. X          else if (color[l] == white)
  195. X        printf (" %c", Qxx[board[l]]);
  196. X          else
  197. X        printf (" %c", Pxx[board[l]]);
  198. X        }
  199. X      printf ("\n");
  200. X    }
  201. X      printf ("\n");
  202. X    }
  203. X}
  204. X
  205. Xint
  206. Xcastle (short int side, short int kf, short int kt, short int iop)
  207. X
  208. X/* Make or Unmake a castling move. */
  209. X
  210. X{
  211. X  register short rf, rt, xside;
  212. X
  213. X  xside = otherside[side];
  214. X  if (kt > kf)
  215. X    {
  216. X      rf = kf + 3;
  217. X      rt = kt - 1;
  218. X    }
  219. X  else
  220. X    {
  221. X      rf = kf - 4;
  222. X      rt = kt + 1;
  223. X    }
  224. X  if (kf != kingP[side] ||
  225. X      board[kf] != king ||
  226. X      board[rf] != rook ||
  227. X      color[kt] != neutral ||
  228. X      color[rt] != neutral ||
  229. X      color[kt - 1] != neutral)
  230. X    return (false);
  231. X  else
  232. X    return (true);
  233. X}
  234. X
  235. Xvoid
  236. XInitialize_moves (void)
  237. X
  238. X/*
  239. X * This procedure pre-calculates all moves for every piece from every square.
  240. X * This data is stored in nextpos/nextdir and used later in the move
  241. X * generation routines.
  242. X */
  243. X
  244. X{
  245. X  short ptyp, po, p0, d, di, s, delta;
  246. X  unsigned char *ppos, *pdir;
  247. X  short dest[8][8];
  248. X  short steps[8];
  249. X  short sorted[8];
  250. X
  251. X  for (ptyp = 0; ptyp < 8; ptyp++)
  252. X    for (po = 0; po < 64; po++)
  253. X      for (p0 = 0; p0 < 64; p0++)
  254. X    {
  255. X      nextpos[ptyp][po][p0] = (unsigned char) po;
  256. X      nextdir[ptyp][po][p0] = (unsigned char) po;
  257. X    }
  258. X  for (ptyp = 1; ptyp < 8; ptyp++)
  259. X    for (po = 21; po < 99; po++)
  260. X      if (nunmap[po] >= 0)
  261. X    {
  262. X      ppos = nextpos[ptyp][nunmap[po]];
  263. X      pdir = nextdir[ptyp][nunmap[po]];
  264. X      /* dest is a function of direction and steps */
  265. X      for (d = 0; d < 8; d++)
  266. X        {
  267. X          dest[d][0] = nunmap[po];
  268. X          delta = direc[ptyp][d];
  269. X          if (delta != 0)
  270. X        {
  271. X          p0 = po;
  272. X          for (s = 0; s < max_steps[ptyp]; s++)
  273. X            {
  274. X              p0 = p0 + delta;
  275. X
  276. X              /*
  277. X               * break if (off
  278. X               * board) or (pawns
  279. X               * only move two
  280. X               * steps from home
  281. X               * square)
  282. X               */
  283. X              if ((nunmap[p0] < 0) || (((ptyp == pawn) || (ptyp == bpawn))
  284. X                           && ((s > 0) && ((d > 0) || (Stboard[nunmap[po]] != pawn)))))
  285. X            break;
  286. X              else
  287. X            dest[d][s] = nunmap[p0];
  288. X            }
  289. X        }
  290. X          else
  291. X        s = 0;
  292. X
  293. X          /*
  294. X           * sort dest in number of steps order
  295. X           * currently no sort is done due to
  296. X           * compability with the move
  297. X           * generation order in old gnu chess
  298. X           */
  299. X          steps[d] = s;
  300. X          for (di = d; s > 0 && di > 0; di--)
  301. X        if (steps[sorted[di - 1]] == 0)    /* should be: < s */
  302. X          sorted[di] = sorted[di - 1];
  303. X        else
  304. X          break;
  305. X          sorted[di] = d;
  306. X        }
  307. X
  308. X      /*
  309. X       * update nextpos/nextdir, pawns have two
  310. X       * threads (capture and no capture)
  311. X       */
  312. X      p0 = nunmap[po];
  313. X      if (ptyp == pawn || ptyp == bpawn)
  314. X        {
  315. X          for (s = 0; s < steps[0]; s++)
  316. X        {
  317. X          ppos[p0] = (unsigned char) dest[0][s];
  318. X          p0 = dest[0][s];
  319. X        }
  320. X          p0 = nunmap[po];
  321. X          for (d = 1; d < 3; d++)
  322. X        {
  323. X          pdir[p0] = (unsigned char) dest[d][0];
  324. X          p0 = dest[d][0];
  325. X        }
  326. X        }
  327. X      else
  328. X        {
  329. X          pdir[p0] = (unsigned char) dest[sorted[0]][0];
  330. X          for (d = 0; d < 8; d++)
  331. X        for (s = 0; s < steps[sorted[d]]; s++)
  332. X          {
  333. X            ppos[p0] = (unsigned char) dest[sorted[d]][s];
  334. X            p0 = dest[sorted[d]][s];
  335. X            if (d < 7)
  336. X              pdir[p0] = (unsigned char) dest[sorted[d + 1]][0];
  337. X
  338. X            /*
  339. X             * else is already
  340. X             * initialized
  341. X             */
  342. X          }
  343. X        }
  344. X    }
  345. X}
  346. X
  347. X#define Link(from,to,flag,s) \
  348. X{\
  349. X   node->f = from; node->t = to;\
  350. X     node->reply = 0;\
  351. X       node->flags = flag;\
  352. X     node->score = s;\
  353. X       ++node;\
  354. X         ++mvptr;\
  355. X         }
  356. X
  357. Xinline void
  358. XLinkMove (short int ply,
  359. X      short int f,
  360. X      short int t,
  361. X      short int flag,
  362. X      short int xside)
  363. X
  364. X/*
  365. X * Add a move to the tree.  Assign a bonus to order the moves as follows: 1.
  366. X * Principle variation 2. Capture of last moved piece 3. Other captures
  367. X * (major pieces first) 4. Killer moves 5.
  368. X */
  369. X
  370. X{
  371. X  register short s;
  372. X  register unsigned short mv;
  373. X  register struct leaf *node;
  374. X
  375. X  s = 0;
  376. X  node = &Tree[mvptr];
  377. X  mv = (f << 8) | t;
  378. X  if (row (t) == 0 || row (t) == 7)
  379. X    {
  380. X      flag |= promote;
  381. X      Link (f, t, flag | queen, s - 20000);
  382. X      Link (f, t, flag | knight, s - 20000);
  383. X      Link (f, t, flag | rook, s - 20000);
  384. X      flag |= bishop;
  385. X    }
  386. X  else if (row (t) == 1 || row (t) == 6)
  387. X    {
  388. X      flag |= pwnthrt;
  389. X    }
  390. X  Link (f, t, flag, s - 20000);
  391. X}
  392. X
  393. X
  394. Xvoid
  395. XGenMoves (register short int ply, register short int sq, short int side, short int xside)
  396. X
  397. X/*
  398. X * Generate moves for a piece. The moves are taken from the precalulated
  399. X * array nextpos/nextdir. If the board is free, next move is choosen from
  400. X * nextpos else from nextdir.
  401. X */
  402. X
  403. X{
  404. X  register short u, piece;
  405. X  register unsigned char *ppos, *pdir;
  406. X
  407. X  mvptr = 0;
  408. X  piece = board[sq];
  409. X  ppos = nextpos[ptype[side][piece]][sq];
  410. X  pdir = nextdir[ptype[side][piece]][sq];
  411. X  if (piece == pawn)
  412. X    {
  413. X      u = ppos[sq];        /* follow no captures thread */
  414. X      if (color[u] == neutral)
  415. X    {
  416. X      LinkMove (ply, sq, u, 0, xside);
  417. X      u = ppos[u];
  418. X      if (color[u] == neutral)
  419. X        LinkMove (ply, sq, u, 0, xside);
  420. X    }
  421. X      u = pdir[sq];        /* follow captures thread */
  422. X      if (color[u] == xside)
  423. X    LinkMove (ply, sq, u, capture, xside);
  424. X      else if (u == epsquare)
  425. X    LinkMove (ply, sq, u, capture | epmask, xside);
  426. X      u = pdir[u];
  427. X      if (color[u] == xside)
  428. X    LinkMove (ply, sq, u, capture, xside);
  429. X      else if (u == epsquare)
  430. X    LinkMove (ply, sq, u, capture | epmask, xside);
  431. X
  432. X    }
  433. X  else
  434. X    {
  435. X      u = ppos[sq];
  436. X      do
  437. X    {
  438. X      if (color[u] == neutral)
  439. X        {
  440. X          LinkMove (ply, sq, u, 0, xside);
  441. X          u = ppos[u];
  442. X        }
  443. X      else
  444. X        {
  445. X          if (color[u] == xside)
  446. X        LinkMove (ply, sq, u, capture, xside);
  447. X          u = pdir[u];
  448. X        }
  449. X      } while (u != sq);
  450. X    }
  451. X}
  452. Xvoid
  453. Xskip ()
  454. X{
  455. X  while (*InPtr != ' ')
  456. X    InPtr++;
  457. X  while (*InPtr == ' ')
  458. X    InPtr++;
  459. X}
  460. Xvoid
  461. Xskipb ()
  462. X{
  463. X  while (*InPtr == ' ')
  464. X    InPtr++;
  465. X}
  466. Xint
  467. Xparser (char *f, int side, unsigned short *flags)
  468. X{
  469. X  int c1, r1, c2, r2;
  470. X
  471. X  *flags = 0;
  472. X
  473. X  if (f[4] == 'o')
  474. X    if (side == black)
  475. X      return 0x3C3A;
  476. X    else
  477. X      return 0x0402;
  478. X  else if (f[0] == 'o')
  479. X    if (side == black)
  480. X      return 0x3C3E;
  481. X    else
  482. X      return 0x0406;
  483. X  else
  484. X    {
  485. X      c1 = f[0] - 'a';
  486. X      r1 = f[1] - '1';
  487. X      c2 = f[2] - 'a';
  488. X      r2 = f[3] - '1';
  489. X      if (f[4] != ' ')
  490. X    {
  491. X      /* promotion */
  492. X      for (i = 0; i < 7; i++)
  493. X        if (f[4] == Qxx[i])
  494. X          {
  495. X        *flags = i | promote;
  496. X        break;
  497. X          }
  498. X    }
  499. X      return (locn (r1, c1) << 8) | locn (r2, c2);
  500. X    }
  501. X  return (0);
  502. X}
  503. X
  504. Xvoid
  505. Xalgbr (short int f, short int t, short int flag)
  506. X
  507. X
  508. X/*
  509. X * Generate move strings in different formats.
  510. X */
  511. X
  512. X{
  513. X  int m3p;
  514. X
  515. X  if (f != t)
  516. X    {
  517. X      /* algebraic notation */
  518. X      mvstr[0][0] = Cxx[column (f)];
  519. X      mvstr[0][1] = Rxx[row (f)];
  520. X      mvstr[0][2] = Cxx[column (t)];
  521. X      mvstr[0][3] = Rxx[row (t)];
  522. X      mvstr[0][4] = mvstr[3][0] = '\0';
  523. X      if (((mvstr[1][0] = Pxx[board[f]]) == 'P') || (flag & promote))
  524. X    {
  525. X      if (mvstr[0][0] == mvstr[0][2])    /* pawn did not eat */
  526. X        {
  527. X          mvstr[2][0] = mvstr[1][0] = mvstr[0][2];    /* to column */
  528. X          mvstr[2][1] = mvstr[1][1] = mvstr[0][3];    /* to row */
  529. X          m3p = 2;
  530. X        }
  531. X      else
  532. X        /* pawn ate */
  533. X        {
  534. X          mvstr[2][0] = mvstr[1][0] = mvstr[0][0];    /* column */
  535. X          mvstr[2][1] = mvstr[1][1] = mvstr[0][2];    /* to column */
  536. X          mvstr[2][2] = mvstr[0][3];
  537. X          m3p = 3;        /* to row */
  538. X        }
  539. X      if (flag & promote)
  540. X        {
  541. X          mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = Qxx[flag & pmask];
  542. X          mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[0][5] = '\0';
  543. X#ifdef CHESSTOOL
  544. X          mvstr[3][0] = mvstr[0][0];    /* Allow e7e8 for
  545. X                         * chesstool */
  546. X          mvstr[3][1] = mvstr[0][1];
  547. X          mvstr[3][2] = mvstr[0][2];
  548. X          mvstr[3][3] = mvstr[0][3];
  549. X          mvstr[3][4] = '\0';
  550. X#endif
  551. X        }
  552. X      mvstr[2][m3p] = mvstr[1][2] = '\0';
  553. X    }
  554. X      else
  555. X    /* not a pawn */
  556. X    {
  557. X      mvstr[2][0] = mvstr[1][0];
  558. X      mvstr[2][1] = mvstr[0][1];
  559. X      mvstr[2][2] = mvstr[1][1] = mvstr[0][2];    /* to column */
  560. X      mvstr[2][3] = mvstr[1][2] = mvstr[0][3];    /* to row */
  561. X      mvstr[2][4] = mvstr[1][3] = '\0';
  562. X      strcpy (mvstr[3], mvstr[2]);
  563. X      mvstr[3][1] = mvstr[0][0];
  564. X      if (flag & cstlmask)
  565. X        {
  566. X          if (t > f)
  567. X        {
  568. X          strcpy (mvstr[1], "o-o");
  569. X          strcpy (mvstr[2], "O-O");
  570. X        }
  571. X          else
  572. X        {
  573. X          strcpy (mvstr[1], "o-o-o");
  574. X          strcpy (mvstr[2], "O-O-O");
  575. X        }
  576. X        }
  577. X    }
  578. X    }
  579. X  else
  580. X    mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
  581. X}
  582. X
  583. XGetGame ()
  584. X{
  585. X  char fb[256];
  586. X  unsigned short flags;
  587. X
  588. X  fgets (fb, 256, fd);
  589. X  fgets (fb, 256, fd);
  590. X  while (fgets (fb, 256, fd))
  591. X    {
  592. X      struct GameRec *g;
  593. X      int side = white;
  594. X
  595. X      side = otherside[side];
  596. X      if (fb[0] == '\n')
  597. X    return;
  598. X      ++GameCnt;
  599. X      InPtr = fb;
  600. X      skipb ();
  601. X      g = &GameList[GameCnt];
  602. X      g->gmove = parser (InPtr, side, &flags);
  603. X      skip ();
  604. X      g->score = atoi (InPtr);
  605. X      skip ();
  606. X      g->depth = atoi (InPtr);
  607. X      skip ();
  608. X      g->nodes = atoi (InPtr);
  609. X      skip ();
  610. X      g->time = atoi (InPtr);
  611. X      g->flags = flags;
  612. X      skip ();
  613. X      ++GameCnt;
  614. X      g = &GameList[GameCnt];
  615. X      g->gmove = parser (InPtr, side, &flags);
  616. X      skip ();
  617. X      g->score = atoi (InPtr);
  618. X      skip ();
  619. X      g->depth = atoi (InPtr);
  620. X      skip ();
  621. X      g->nodes = atoi (InPtr);
  622. X      skip ();
  623. X      g->time = atoi (InPtr);
  624. X      g->flags = flags;
  625. X
  626. X    }
  627. X}
  628. Xshort int xside, side;
  629. Xint
  630. Xgetboard (int mvno)
  631. X
  632. X{
  633. X  register short int f, t;
  634. X  short int rf, rt;
  635. X  unsigned short mv;
  636. X
  637. X
  638. X  /* now update the board and hash values */
  639. X
  640. X  /*
  641. X   * should really check the moves as we do this, but???
  642. X   */
  643. X  mv = GameList[mvno].gmove;
  644. X  f = mv >> 8 & 0x7F;
  645. X  t = mv & 0xFF;
  646. X  /* can only capture other side */
  647. X  if (board[t] != no_piece)
  648. X    {
  649. X      if (color[t] != xside)
  650. X    {
  651. X      algbr (f, t, 0);
  652. X      printf ("Illegal move - %d %s \n", mvno, mvstr);
  653. X    }
  654. X    }
  655. X  /* there must be a piece to move */
  656. X  if (board[f] == no_piece || color[f] != side)
  657. X    {
  658. X      algbr (f, t, 0);
  659. X      printf ("Illegal move + %d %s \n", mvno, mvstr);
  660. X    }
  661. X  /* is it EnPassant */
  662. X
  663. X
  664. X  if (board[f] == pawn && board[t] == no_piece)
  665. X    {
  666. X      if ((row (f) == 3 &&
  667. X       row (t) == 2) || (row (f) == 4 && row (t) == 5))
  668. X    {
  669. X      if (column (t) != column (f))
  670. X        {
  671. X          ep = t + ((t > f) ? -8 : 8);
  672. X          if (board[ep] == pawn && color[ep] == xside)
  673. X        {
  674. X          board[ep] = no_piece;
  675. X          color[ep] = neutral;
  676. X        }
  677. X        }
  678. X    }
  679. X    }
  680. X  board[t] = board[f];
  681. X  color[t] = color[f];
  682. X  color[f] = neutral;
  683. X  board[f] = no_piece;
  684. X  /* castle moves */
  685. X  if ((mv == BLACKCASTLE) || (mv == WHITECASTLE) || (mv == LONGBLACKCASTLE) || (mv == LONGWHITECASTLE))
  686. X    {
  687. X
  688. X      if (t > f)
  689. X    {
  690. X      rf = f + 3;
  691. X      rt = t - 1;
  692. X    }
  693. X      else
  694. X    {
  695. X      rf = f - 4;
  696. X      rt = t + 1;
  697. X    }
  698. X      if ((board[t] == king && color[t] == side) && (board[rf] == rook) && (color[rf] == side))
  699. X    {
  700. X      board[rt] = rook;
  701. X      color[rt] = side;
  702. X      board[rf] = no_piece;
  703. X      color[rf] = neutral;
  704. X      ckcastld[side] = true;
  705. X    }
  706. X    }
  707. X  else if (GameList[i].flags & promote)
  708. X
  709. X    board[t] = GameList[i].flags & pmask;
  710. X}
  711. X
  712. Xint
  713. Xmain (int argc, char **argv)
  714. X{
  715. X  int from, to;
  716. X  unsigned short int mv;
  717. X  int start, end;
  718. X  int ii, kf, jj;
  719. X
  720. X  Initialize_moves ();
  721. X  ckcastld[0] = ckcastld[1] = false;
  722. X
  723. X  if (argc > 4 || argc < 2)
  724. X    {
  725. X      printf ("Usage: game file [start [end] ] \n");
  726. X      exit ();
  727. X    }
  728. X  start = end = 0;
  729. X
  730. X  if (argc > 2)
  731. X    start = (atoi (argv[2]) * 2) - 1;
  732. X  if (argc == 4)
  733. X    end = (atoi (argv[3]) * 2) - 1;
  734. X  side = white;
  735. X  xside = black;
  736. X  for (i = 0; i < 64; i++)
  737. X    {
  738. X      board[i] = Stboard[i];
  739. X      color[i] = Stcolor[i];
  740. X    }
  741. X  i = 1;
  742. X  if ((fd = fopen (argv[1], RWA_ACC)) == NULL)
  743. X    exit (1);
  744. X  GetGame ();
  745. X  if (!start || start < 1 || start > GameCnt)
  746. X    start = 1;
  747. X  if (!end || end > GameCnt || end < 1)
  748. X    end = GameCnt;
  749. X  side = white;
  750. X  xside = black;
  751. X  for (i = 1; i < end; i++)
  752. X    {
  753. X      mv = GameList[i].gmove;
  754. X      from = mv >> 8 & 0x7F;
  755. X      to = mv & 0x7F;
  756. X      algbr (from, to, 0);
  757. X      if (side)
  758. X    printf ("%s\n", mvstr);
  759. X      else
  760. X    {
  761. X      printf ("%d. ", 1 + ((i - 1) / 2));
  762. X      printf ("%s  ", mvstr);
  763. X    }
  764. X
  765. X      GenMoves (0, from, side, xside);
  766. X      if (!ckcastld[side] && board[from] == king && color[from] == side)
  767. X    {
  768. X      if (castle (side, from, from + 2, 0))
  769. X        {
  770. X          LinkMove (0, from, from + 2, cstlmask, xside);
  771. X        }
  772. X      if (castle (side, from, from - 2, 0))
  773. X        {
  774. X          LinkMove (0, from, from - 2, cstlmask, xside);
  775. X        }
  776. X    }
  777. X      ok = false;
  778. X      for (ii = 0; ii < mvptr; ii++)
  779. X    {
  780. X      if (from == Tree[ii].f && to == Tree[ii].t)
  781. X        {
  782. X          ok = true;
  783. X          break;
  784. X        }
  785. X    }
  786. X      if (!ok)
  787. X    {
  788. X      algbr (from, to, 0);
  789. X      printf ("Illegal move %s\n", mvstr);
  790. X      for (ii = 0; ii < mvptr; ii++)
  791. X        {
  792. X          algbr (Tree[ii].f, Tree[ii].t, 0);
  793. X          printf (" %s\n", mvstr);
  794. X        }
  795. X      DISP ();
  796. X      exit ();
  797. X    }
  798. X      getboard (i);
  799. X      if (board[to] == pawn)
  800. X    if (to - from == 16)
  801. X      epsquare = from + 8;
  802. X    else if (from - to == 16)
  803. X      epsquare = from - 8;
  804. X    else
  805. X      epsquare = -1;
  806. X      kf = -1;
  807. X      for (ii = 0; ii < 64; ii++)
  808. X    {
  809. X      if ((board[ii] == king) && (color[ii] == side))
  810. X        {
  811. X          kf = ii;
  812. X          break;
  813. X        }
  814. X    }
  815. X      if (kf < 0)
  816. X    {
  817. X      printf ("Badnews: you have no king\n");
  818. X      DISP ();
  819. X      exit ();
  820. X    }
  821. X      for (ii = 0; ii < 64; ii++)
  822. X    {
  823. X      if (color[ii] == xside)
  824. X        {
  825. X          mvptr = 0;
  826. X          GenMoves (0, ii, xside, side);
  827. X          for (jj = 0; jj < mvptr; jj++)
  828. X        {
  829. X          if (Tree[jj].t == kf)
  830. X            {
  831. X
  832. X              printf ("Badnews: you are in check\n");
  833. X              printf ("king is at %d %d\n", row (kf), column (kf));
  834. X              algbr (Tree[jj].f, Tree[jj].t, 0);
  835. X              printf ("move is %s\n", mvstr);
  836. X              DISP ();
  837. X              exit ();
  838. X            }
  839. X        }
  840. X        }
  841. X    }
  842. X      xside = side;
  843. X      side = otherside[side];
  844. X    }
  845. X  printf ("\n\n");
  846. X  printf ("Final board:\n\n");
  847. X  DISP ();
  848. X  exit ();
  849. X}
  850. END_OF_FILE
  851. if test 18324 -ne `wc -c <'src/checkgame.c'`; then
  852.     echo shar: \"'src/checkgame.c'\" unpacked with wrong size!
  853. fi
  854. # end of 'src/checkgame.c'
  855. fi
  856. if test -f 'src/search.c' -a "${1}" != "-c" ; then 
  857.   echo shar: Will not clobber existing file \"'src/search.c'\"
  858. else
  859. echo shar: Extracting \"'src/search.c'\" \(32814 characters\)
  860. sed "s/^X//" >'src/search.c' <<'END_OF_FILE'
  861. X/*
  862. X * search.c - C source for GNU CHESS
  863. X *
  864. X * Copyright (c) 1988,1989,1990 John Stanback
  865. X * Copyright (c) 1992 Free Software Foundation
  866. X *
  867. X * This file is part of GNU CHESS.
  868. X *
  869. X * GNU Chess is free software; you can redistribute it and/or modify
  870. X * it under the terms of the GNU General Public License as published by
  871. X * the Free Software Foundation; either version 2, or (at your option)
  872. X * any later version.
  873. X *
  874. X * GNU Chess is distributed in the hope that it will be useful,
  875. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  876. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  877. X * GNU General Public License for more details.
  878. X *
  879. X * You should have received a copy of the GNU General Public License
  880. X * along with GNU Chess; see the file COPYING.  If not, write to
  881. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  882. X */
  883. X#include "gnuchess.h"
  884. X#ifdef QUIETBACKGROUND
  885. Xshort background = 0;
  886. X#endif /* QUIETBACKGROUND */
  887. Xstatic short int DepthBeyond;
  888. Xunsigned short int PrVar[MAXDEPTH];
  889. Xextern char mvstr[4][6];
  890. X#ifdef DEBUG
  891. Xunsigned short DBLINE[MAXDEPTH];
  892. Xstruct leaf *dbptr;
  893. X#endif
  894. Xstruct leaf rootnode;
  895. Xshort int restype;
  896. X#include "ataks.h"
  897. X
  898. X/* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  899. Xinline
  900. Xvoid
  901. Xrepetition (short int *cnt)
  902. X
  903. X/*
  904. X * Check for draw by threefold repetition.
  905. X */
  906. X
  907. X{
  908. X  register short i, c;
  909. X  register unsigned short m;
  910. X  short b[64];
  911. X
  912. X  *cnt = c = 0;
  913. X  /* try to avoid work */
  914. X  if (GameCnt > Game50 + 2)
  915. X    {
  916. X#ifdef NOMEMSET
  917. X      for (i = 0; i < 64; b[i++] = 0) ;
  918. X#else
  919. X      memset ((char *) b, 0, sizeof (b));
  920. X#endif /* NOMEMSET */
  921. X      for (i = GameCnt; i >= Game50; i--)
  922. X    {
  923. X      m = GameList[i].gmove;
  924. X      /* does piece exist on diff board? */
  925. X      if (b[m & 0xff])
  926. X        {
  927. X          /* does diffs cancel out, piece back? */
  928. X          if ((b[m >> 8] += b[m & 0xff]) == 0)
  929. X        --c;
  930. X          b[m & 0xff] = 0;
  931. X        }
  932. X      else
  933. X        {
  934. X          /* create diff */
  935. X          ++c;
  936. X          /* does diff cancel out another diff? */
  937. X          if (!(b[m >> 8] -= (b[m & 0xff] = board[m & 0xff] +
  938. X                  (color[m & 0xff] << 8))))
  939. X        --c;;
  940. X        }
  941. X      /* if diff count is 0 we have a repetition */
  942. X      if (c == 0)
  943. X        if ((i ^ GameCnt) & 1)
  944. X          (*cnt)++;
  945. X    }
  946. X    }
  947. X}
  948. X
  949. Xint plyscore, globalscore, globalpnt;
  950. Xvoid
  951. Xpick (short int p1, short int p2)
  952. X
  953. X/*
  954. X * Find the best move in the tree between indexes p1 and p2. Swap the best
  955. X * move into the p1 element.
  956. X *
  957. X*/
  958. X{
  959. X  register struct leaf *p, *q, *r, *k;
  960. X  register s0;
  961. X  struct leaf temp;
  962. X
  963. X  k = p = &Tree[p1];
  964. X  q = &Tree[p2];
  965. X  s0 = p->score;
  966. X  for (r = p + 1; r <= q; r++)
  967. X    if ((r->score) > s0)
  968. X      {
  969. X    s0 = (r->score);
  970. X    p = r;
  971. X      }
  972. X  if (p != k)
  973. X    {
  974. X      temp = *p;
  975. X      *p = *k;
  976. X      *k = temp;
  977. X    }
  978. X}
  979. X
  980. Xstatic int TCcount, TCleft;
  981. Xvoid
  982. XSelectMove (short int side, short int iop)
  983. X
  984. X
  985. X/*
  986. X * Select a move by calling function search() at progressively deeper ply
  987. X * until time is up or a mate or draw is reached. An alpha-beta window of
  988. X * -Awindow to +Bwindow points is set around the score returned from the
  989. X * previous iteration. If Sdepth != 0 then the program has correctly
  990. X * predicted the opponents move and the search will start at a depth of
  991. X * Sdepth+1 rather than a depth of 1.
  992. X */
  993. X
  994. X{
  995. X  static short int i, tempb, tempc, tempsf, tempst, xside, rpt;
  996. X  static short int alpha, beta, score;
  997. X  static struct GameRec *g;
  998. X  int bookflag = false;
  999. X  int Jscore;
  1000. X  unsigned short tmp[MAXDEPTH];
  1001. X  flag.timeout = false;
  1002. X  xside = side ^ 1;
  1003. X  /* if background mode set to infinite */
  1004. X  if (iop == 2)
  1005. X    {
  1006. X      ResponseTime = 9999999;
  1007. X#ifdef QUIETBACKGROUND
  1008. X      background = true;
  1009. X#endif /* QUIETBACKGROUND */
  1010. X    }
  1011. X  else
  1012. X    {
  1013. X      player = side;
  1014. X      if (TCflag)
  1015. X    {
  1016. X      TCcount = 0;
  1017. X#ifdef QUIETBACKGROUND
  1018. X      background = false;
  1019. X#endif /* QUIETBACKGROUND */
  1020. X      if (TimeControl.moves[side] < 1)
  1021. X        TimeControl.moves[side] = 1;
  1022. X      /* special case time per move specified */
  1023. X      if (TimeControl.moves[side] == 1)
  1024. X        {
  1025. X          ResponseTime = TimeControl.clock[side] - 100;
  1026. X          TCleft = 0;
  1027. X        }
  1028. X      else
  1029. X        {
  1030. X          /* calculate avg time per move remaining */
  1031. X          ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) << 1));
  1032. X              TCleft = ResponseTime>>1;
  1033. X           if (TimeControl.moves[side] < 5) TCcount = MAXTCCOUNT - 1;
  1034. X        }
  1035. X      if (ResponseTime < 100)
  1036. X        {
  1037. X          ResponseTime = 100;
  1038. X          TCcount = MAXTCCOUNT;
  1039. X        }
  1040. X      else if (ResponseTime < 200)
  1041. X        {
  1042. X          TCcount = MAXTCCOUNT - 1;
  1043. X        }
  1044. X    }
  1045. X    }
  1046. X
  1047. X  ExtraTime = 0;
  1048. X  ExaminePosition ();
  1049. X  score = ScorePosition (side);
  1050. X#ifdef QUIETBACKGROUND
  1051. X  if (!background)
  1052. X#endif /* QUIETBACKGROUND */
  1053. X    ShowSidetoMove ();
  1054. X  if (TCflag)
  1055. X    if (score < SCORETIME)
  1056. X      {
  1057. X    ExtraTime += TCleft;
  1058. X    TCcount++;
  1059. X      }
  1060. X
  1061. X#ifdef QUIETBACKGROUND
  1062. X  if (!background)
  1063. X#endif /* QUIETBACKGROUND */
  1064. X    SearchStartStuff (side);
  1065. X#if !defined NOHISTORY
  1066. X#ifdef NOMEMSET
  1067. X  for (i = 0; i < 8192; i++)
  1068. X    history[i] = 0;
  1069. X#else
  1070. X  memset ((char *) history, 0, sizeof (history));
  1071. X#endif /* NOMEMSET */
  1072. X#endif
  1073. X  FROMsquare = TOsquare = -1;
  1074. X  PV = 0;
  1075. X  if (iop == 1)
  1076. X    hint = 0;
  1077. X  for (i = 0; i < MAXDEPTH; i++)
  1078. X    PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  1079. X  /* set initial window for search */
  1080. X  alpha = score - ((computer == black) ? BAwindow : WAwindow);
  1081. X  beta = score + ((computer == black) ? BBwindow : WBwindow);
  1082. X  rpt = 0;
  1083. X  TrPnt[1] = 0;
  1084. X  root = &Tree[0];
  1085. X  MoveList (side, 1);
  1086. X  for (i = TrPnt[1]; i < TrPnt[2]; i++) pick (i, TrPnt[2] - 1);
  1087. X  /* can I get a book move? */
  1088. X  if (flag.regularstart && Book){    
  1089. X    flag.timeout = bookflag = OpeningBook (&hint, side);
  1090. X    ResponseTime += ResponseTime;
  1091. X  }
  1092. X  rootnode = Tree[0];
  1093. X  /* zero stats for hash table */
  1094. X  reminus = replus = 0;
  1095. X  NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
  1096. X  globalscore = plyscore = score;
  1097. X#ifdef DEBUG4
  1098. X  if (debuglevel & 8)
  1099. X    {
  1100. X      int j;
  1101. X      for (j = 1; j < 2; j++)
  1102. X    {
  1103. X      int idb;
  1104. X      for (idb = TrPnt[j]; idb < TrPnt[j + 1]; idb++)
  1105. X        {
  1106. X          algbr (Tree[idb].f, Tree[idb].t, Tree[idb].flags);
  1107. X          printf ("level 8 %d-->%d %s %d %d\n", j, idb, mvstr[0], Tree[idb].score, Tree[idb].width);
  1108. X        }
  1109. X    }
  1110. X    }
  1111. X#endif
  1112. X
  1113. X/********************* main loop ********************************/
  1114. X  while (!flag.timeout)
  1115. X    {
  1116. X      /* go down a level at a time */
  1117. X      Sdepth++;
  1118. X      DepthBeyond = Sdepth + ((Sdepth == 1) ? (DEPTHBEYOND >> 1) : DEPTHBEYOND);
  1119. X
  1120. X#if !defined CHESSTOOL && !defined XBOARD
  1121. X#ifdef QUIETBACKGROUND
  1122. X      if (!background)
  1123. X#endif /* QUIETBACKGROUND */
  1124. X    ShowDepth (' ');
  1125. X#endif
  1126. X      /* search at this level returns score of PV */
  1127. X      score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  1128. X      /* save PV as killer */
  1129. X      for (i = 1; i <= Sdepth; i++)
  1130. X    killr0[i] = PrVar[i];
  1131. X
  1132. X      /* low search failure re-search with (-inf,score) limits  */
  1133. X      if (score < alpha)
  1134. X    {
  1135. X      reminus++;
  1136. X#ifdef QUIETBACKGROUND
  1137. X      if (!background)
  1138. X#endif /* QUIETBACKGROUND */
  1139. X        ShowDepth ('-');
  1140. X      if (TCflag && TCcount < MAXTCCOUNT)
  1141. X        {
  1142. X          TCcount += 1;
  1143. X          ExtraTime += (TCleft);
  1144. X        }
  1145. X      score = search (side, 1, Sdepth, -9999, score, PrVar, &rpt);
  1146. X    }
  1147. X
  1148. X      /* high search failure re-search with (score, +inf) limits */
  1149. X      if (score > beta && !(root->flags & exact))
  1150. X    {
  1151. X      replus++;
  1152. X#ifdef QUIETBACKGROUND
  1153. X      if (!background)
  1154. X#endif /* QUIETBACKGROUND */
  1155. X        ShowDepth ('+');
  1156. X      if (TCflag && TCcount < MAXTCCOUNT)
  1157. X        {
  1158. X          TCcount += 1;
  1159. X          ExtraTime += (TCleft);
  1160. X        }
  1161. X      score = search (side, 1, Sdepth, score, 9999, PrVar, &rpt);
  1162. X    }
  1163. X/**************** out of search ********************************************/
  1164. X      if (Sdepth == MaxSearchDepth)
  1165. X    flag.timeout = true;
  1166. X
  1167. X      else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNT))
  1168. X    {
  1169. X      if (tmp[1] != PrVar[1] || tmp[2] != PrVar[2])
  1170. X        {
  1171. X          TCcount++;
  1172. X          ExtraTime += TCleft;
  1173. X        }
  1174. X
  1175. X      if ((abs (score - globalscore) / Sdepth) > ZDELTA)
  1176. X        {
  1177. X          TCcount++;
  1178. X          ExtraTime += TCleft;
  1179. X        }
  1180. X    }
  1181. X/************************ time control ***********************************/
  1182. X
  1183. X      /* save PV as killer */
  1184. X      for (i = 1; i <= Sdepth + 1; i++)
  1185. X    killr0[i] = PrVar[i];
  1186. X      if (((rootnode.f << 8) | rootnode.t) != PrVar[1])
  1187. X    {
  1188. X      for (i = TrPnt[1]; i < TrPnt[2]; i++)
  1189. X        if (((Tree[i].f << 8) | Tree[i].t) == PrVar[1])
  1190. X          {
  1191. X        rootnode = Tree[i];
  1192. X        break;
  1193. X          }
  1194. X    }
  1195. X      for (i = 1; i <= Sdepth + 1; i++)
  1196. X    tmp[i] = PrVar[i];
  1197. X      Tscore[0] = score;
  1198. X      /*if (!flag.timeout)*/
  1199. X      for (i = TrPnt[1]; i < TrPnt[2]; i++)
  1200. X    pick (i, TrPnt[2] - 1);
  1201. X      /* if done or nothing good to look at quit */
  1202. X      if ((rootnode.flags & exact) || (score < -9000))
  1203. X    flag.timeout = true;
  1204. X#ifdef DEBUG13
  1205. X      if (flag.timeout && !background)
  1206. X    {
  1207. X      FILE *D;
  1208. X      int r, c, l;
  1209. X      struct leaf *xnode;
  1210. X      D = fopen ("/tmp/DEBUG", "a+");
  1211. X      fprintf (D, " %d ply %d sco %d TC %d rs %d gl %d cnt %d\n",
  1212. X           Sdepth, plyscore, score, TCcount, restype,
  1213. X           globalpnt, TrPnt[2] - TrPnt[1]);
  1214. X      for (i = 1; tmp[i]; i++)
  1215. X        {
  1216. X          algbr (tmp[i] >> 8, tmp[i] & 0xff, 0);
  1217. X          fprintf (D, "%s ", mvstr[0]);
  1218. X        }
  1219. X      fprintf (D, "\n");
  1220. X      for (i = 1; PrVar[i]; i++)
  1221. X        {
  1222. X          algbr (PrVar[i] >> 8, PrVar[i] & 0xff, 0);
  1223. X          fprintf (D, "%s ", mvstr[0]);
  1224. X        }
  1225. X      fprintf (D, "\n");
  1226. X      algbr (rootnode.f, rootnode.t, rootnode.flags);
  1227. X      fprintf (D, "%s ", mvstr[0]);
  1228. X      fprintf (D, "\n");
  1229. X      fclose (D);
  1230. X    }
  1231. X#endif
  1232. X      /* find the next best move put below root */
  1233. X      if (!flag.timeout)
  1234. X    {
  1235. X      /* */
  1236. X#if !defined NODYNALPHA
  1237. X      Jscore = (plyscore + score) >> 1;
  1238. X#endif
  1239. X      plyscore = score;
  1240. X      /* recompute search window */
  1241. X      beta = score + ((computer == black) ? BBwindow : WBwindow);
  1242. X#if !defined NODYNALPHA
  1243. X      alpha = ((Jscore < score) ? Jscore : score) - ((computer == black) ? BAwindow : WAwindow) + abs (Jscore / 12);
  1244. X#else
  1245. X      alpha = score - ((computer == black) ? BAwindow : WAwindow);
  1246. X#endif
  1247. X    }
  1248. X      else
  1249. X    for (i = 1; i <= Sdepth + 1; i++)
  1250. X      PrVar[i] = tmp[i];
  1251. X#if !defined CHESSTOOL
  1252. X#ifdef QUIETBACKGROUND
  1253. X      if (!background)
  1254. X#endif /* QUIETBACKGROUND */
  1255. X    ShowResults (score, PrVar, '.');
  1256. X#endif
  1257. X#ifdef DEBUG4
  1258. X      if (debuglevel & 16)
  1259. X    {
  1260. X      int j;
  1261. X      printf ("Sdepth %d alpha %d beta %d stage %d\n", Sdepth, alpha, beta, stage);
  1262. X      for (j = 1; j < 2; j++)
  1263. X        {
  1264. X          int idb;
  1265. X          for (idb = TrPnt[j]; idb < TrPnt[j + 1]; idb++)
  1266. X        {
  1267. X          algbr (Tree[idb].f, Tree[idb].t, Tree[idb].flags);
  1268. X          printf ("level 16 %d-->%d %s %d %d %x\n", Sdepth, idb, mvstr[0], Tree[idb].score, Tree[idb].width, Tree[idb].flags);
  1269. X        }
  1270. X        }
  1271. X    }
  1272. X#endif
  1273. X
  1274. X    }
  1275. X/******************************* end of main loop ***********************************/
  1276. X  /* background mode */
  1277. X  if (iop == 2)
  1278. X    return;
  1279. X#ifdef DEBUG4
  1280. X  if (debuglevel & 4)
  1281. X    {
  1282. X      int j;
  1283. X      printf ("Sdepth %d alpha %d beta %d stage %d\n", Sdepth, alpha, beta, stage);
  1284. X      for (j = 1; j < 2; j++)
  1285. X    {
  1286. X      int idb;
  1287. X      for (idb = TrPnt[j]; idb < TrPnt[j + 1]; idb++)
  1288. X        {
  1289. X          algbr (Tree[idb].f, Tree[idb].t, Tree[idb].flags);
  1290. X          printf ("level 4 %d-->%d %s %d %d\n", j, idb, mvstr[0], Tree[idb].score, Tree[idb].width);
  1291. X        }
  1292. X    }
  1293. X    }
  1294. X#endif
  1295. X
  1296. X  if (rpt >= 2)
  1297. X    {
  1298. X      rootnode.flags |= draw;
  1299. X      DRAW = CP[101];        /*Repetition*/
  1300. X    }
  1301. X  else
  1302. X    /* if no moves and not in check then draw */
  1303. X  if ((rootnode.score == -9999) && !(SqAtakd (PieceList[side][0], xside)))
  1304. X    {
  1305. X      rootnode.flags |= draw;
  1306. X      DRAW = CP[87];        /*No moves*/
  1307. X    }
  1308. X  else if (GameCnt == MAXMOVES)
  1309. X    {
  1310. X      rootnode.flags |= draw;
  1311. X      DRAW = CP[80];        /*Max Moves*/
  1312. X    }
  1313. X
  1314. X  /* not in book so set hint to guessed move for other side */
  1315. X  if (!bookflag)
  1316. X    hint = ((tmp[1]) ? tmp[2] : 0);
  1317. X
  1318. X  /* if not mate or draw make move and output it */
  1319. X  if (((score > -9999) && (rpt <= 2)) || (rootnode.flags & draw))
  1320. X    {
  1321. X      MakeMove (side, &rootnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  1322. X#if !defined NOMATERIAL
  1323. X      if (flag.material && !pmtl[black] && !pmtl[white] && (mtl[white] < (valueR + valueK)) && (mtl[black] < (valueR + valueK)))
  1324. X    {
  1325. X      rootnode.flags |= draw;
  1326. X      DRAW = CP[224];    /*No pieces*/
  1327. X    }
  1328. X      else
  1329. X#endif
  1330. X      if (!PieceCnt[black] && !PieceCnt[white])
  1331. X    {
  1332. X      rootnode.flags |= draw;
  1333. X      DRAW = CP[88];    /*No pieces*/
  1334. X    }
  1335. X      algbr (rootnode.f, rootnode.t, (short) rootnode.flags);
  1336. X    }
  1337. X  else {
  1338. X    algbr (0, 0, 0);        /* Zero move string when mate. */
  1339. X    rootnode.score = score;    /* When mate, ignore distinctions! --SMC */
  1340. X  }
  1341. X  /* If Time Control get the elapsed time */
  1342. X  if (TCflag)
  1343. X    ElapsedTime (1);
  1344. X  OutputMove ();
  1345. X  /* if mate set flag */
  1346. X  if ((score == -9999 || score == 9998))
  1347. X    flag.mate = true;
  1348. X  /* if mate clear hint */
  1349. X  if (flag.mate)
  1350. X    hint = 0;
  1351. X  /* if pawn move or capture or castle or promote zero repitition array */
  1352. X  if ((board[rootnode.t] == pawn) || (rootnode.flags & (capture | cstlmask | promote)))
  1353. X    {
  1354. X      Game50 = GameCnt;
  1355. X      ZeroRPT ();
  1356. X    }
  1357. X  /* add move to game list */
  1358. X  g = &GameList[GameCnt];
  1359. X  g->score = score;
  1360. X  g->nodes = NodeCnt;
  1361. X  g->time = (short) et;
  1362. X  g->depth = Sdepth;
  1363. X  g->flags = root->flags;
  1364. X#ifdef DEBUG40
  1365. X  g->d1 = TCcount;
  1366. X  g->d2 = ResponseTime ;
  1367. X  g->d4 = TCleft;
  1368. X  g->d3 = ExtraTime;
  1369. X#endif
  1370. X  /* update time comtrol info */
  1371. X  if (TCflag)
  1372. X    {
  1373. X#if defined CHESSTOOL || defined XBOARD
  1374. X      TimeControl.clock[side] -= (et + OperatorTime + 45);
  1375. X#else
  1376. X      TimeControl.clock[side] -= (et + OperatorTime);
  1377. X#endif
  1378. X      /* finished our required moves - setup the next set */
  1379. X      if (--TimeControl.moves[side] == 0)
  1380. X    {
  1381. X      if (XC)
  1382. X        if (XCmore < XC)
  1383. X          {
  1384. X        TCmoves = XCmoves[XCmore];
  1385. X        TCminutes = XCminutes[XCmore];
  1386. X        TCseconds = XCseconds[XCmore];
  1387. X        XCmore++;
  1388. X          }
  1389. X      SetTimeControl ();
  1390. X    }
  1391. X    }
  1392. X  /* check for end conditions */
  1393. X  if ((rootnode.flags & draw) /*&& flag.bothsides*/ )
  1394. X    flag.quit = flag.mate = true;
  1395. X  else if (GameCnt == MAXMOVES)
  1396. X    {
  1397. X      flag.quit = flag.mate = true;
  1398. X    }
  1399. X  /* out of move store, you loose */
  1400. X  else
  1401. X    /* switch to other side */
  1402. X    player = xside;
  1403. X  Sdepth = 0;
  1404. X}
  1405. X
  1406. Xint
  1407. Xsearch (short int side,
  1408. X    register short int ply,
  1409. X    register short int depth,
  1410. X    short int alpha,
  1411. X    short int beta,
  1412. X    short unsigned int *bstline,
  1413. X    short int *rpt)
  1414. X
  1415. X/*
  1416. X * Perform an alpha-beta search to determine the score for the current board
  1417. X * position. If depth <= 0 only capturing moves, pawn promotions and
  1418. X * responses to check are generated and searched, otherwise all moves are
  1419. X * processed. The search depth is modified for check evasions, certain
  1420. X * re-captures and threats. Extensions may continue for up to 11 ply beyond
  1421. X * the nominal search depth.
  1422. X */
  1423. X
  1424. X
  1425. X{
  1426. X  register short j, pnt;
  1427. X  short tempb, tempc, tempsf, tempst, cf;
  1428. X  short xside, pbst, score, rcnt, slk, InChk;
  1429. X  unsigned short mv, nxtline[MAXDEPTH];
  1430. X  struct leaf *node, tmp;
  1431. X  short best;
  1432. X  short bestwidth = 0;
  1433. X
  1434. X  NodeCnt++;
  1435. X  /* look every ZNODE nodes for a timeout */
  1436. X  if (TCflag)
  1437. X    {
  1438. X      if (NodeCnt > ETnodes)
  1439. X    {
  1440. X      ElapsedTime (2);
  1441. X      if (Sdepth > MINDEPTH && flag.musttimeout)
  1442. X        {
  1443. X          flag.timeout = true;
  1444. X          flag.musttimeout = false;
  1445. X        }
  1446. X      else if ((et >= (ResponseTime + ExtraTime)) && Sdepth > MINDEPTH)
  1447. X        flag.timeout = true;
  1448. X    }
  1449. X
  1450. X    }
  1451. X  else if (flag.musttimeout && Sdepth > MINDEPTH)
  1452. X    {
  1453. X      flag.timeout = true;
  1454. X      flag.musttimeout = false;
  1455. X    }
  1456. X
  1457. X  xside = side ^ 1;
  1458. X
  1459. X  /*
  1460. X   * check for possible repitition if so call repitition - rpt is repeat
  1461. X   * count
  1462. X   */
  1463. X  if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  1464. X    {
  1465. X      repetition (rpt);
  1466. X
  1467. X      /*
  1468. X       * repeat position >2 don't need to return score it's taken care of
  1469. X       * above
  1470. X       */
  1471. X      if (*rpt == 1 && ply > 1)
  1472. X    return 0;
  1473. X    }
  1474. X  else
  1475. X    *rpt = 0;
  1476. X
  1477. X  /* slk is lone king indicator for either side */
  1478. X  score = evaluate (side, ply, alpha, beta, INCscore, &slk, &InChk);
  1479. X  /* score > 9000 its a draw or mate */
  1480. X  if (score > 9000)
  1481. X    {
  1482. X      bstline[ply] = 0;
  1483. X      return (score);
  1484. X    }
  1485. X  /* Do we need to add depth because of special conditions */
  1486. X  /* if in check or pawn threat or in capture sequence search deeper */
  1487. X/*************************************** depth extensions ***********************************/
  1488. X  if (depth > 0)
  1489. X    {
  1490. X      /* Allow opponent a chance to check again */
  1491. X      if (InChk)
  1492. X    depth = (depth < 2) ? 2 : depth;
  1493. X      else if (PawnThreat[ply - 1] ||
  1494. X           (flag.rcptr && (score > alpha) &&
  1495. X      (score < beta) && (ply > 2) && CptrFlag[ply - 1] && CptrFlag[ply - 2]))
  1496. X    ++depth;
  1497. X    }
  1498. X  else
  1499. X    {
  1500. X      if (score >= alpha &&
  1501. X      (InChk || PawnThreat[ply - 1] || (hung[side] > 1 && ply == Sdepth + 1)))
  1502. X    depth = 1;
  1503. X      else if (score <= beta &&
  1504. X           ((ply < Sdepth + 4) && (ply > 4) &&
  1505. X        ChkFlag[ply - 2] && ChkFlag[ply - 4] &&
  1506. X        ChkFlag[ply - 2] != ChkFlag[ply - 4]))
  1507. X    depth = 1;
  1508. X    }
  1509. X/*******************************************************************************************/
  1510. X  /* try the local transition table if it's there */
  1511. X#if ttblsz
  1512. X  if (flag.hash && ply > 1)
  1513. X    {
  1514. X      if (ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true)
  1515. X    {
  1516. X      bstline[ply] = PV;
  1517. X      bstline[ply + 1] = 0;
  1518. X#ifdef DEBUG4
  1519. X      if (debuglevel & 64)
  1520. X        {
  1521. X          algbr (PV >> 8, PV & 0xff, 0);
  1522. X          printf ("-get-> d=%d s=%d p=%d a=%d b=%d %s\n", depth, score, ply, alpha, beta, mvstr[0]);
  1523. X        }
  1524. X#endif
  1525. X      if (beta == -20000)
  1526. X        return (score);
  1527. X      if (alpha > beta)
  1528. X        return (alpha);
  1529. X    }
  1530. X#ifdef HASHFILE
  1531. X      /* ok try the transition file if its there */
  1532. X      else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  1533. X     && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
  1534. X    {
  1535. X      int hgood = false;
  1536. X      int f = PV >> 8;
  1537. X      int t = PV & 0x3f;
  1538. X      register int i;
  1539. X      /*
  1540. X           * if you find something put it in the local table for future
  1541. X           * reference
  1542. X           */
  1543. X      hgood = false;
  1544. X      for (i = TrPnt[ply]; i < TrPnt[ply + 1]; i++)
  1545. X        {
  1546. X          if (Tree[i].f == f && Tree[i].t == t)
  1547. X        {
  1548. X          hgood = true;
  1549. X          break;
  1550. X        }
  1551. X        }
  1552. X      if (hgood)
  1553. X        {
  1554. X          PutInTTable (side, score, depth, ply, alpha, beta, PV);
  1555. X          bstline[ply] = PV;
  1556. X          bstline[ply + 1] = 0;
  1557. X          if (beta == -20000)
  1558. X        return (score);
  1559. X          if (alpha > beta)
  1560. X        return (alpha);
  1561. X        }
  1562. X#ifdef DEBUG10
  1563. X      else
  1564. X        {
  1565. X          FILE *D;
  1566. X          int r, c, l;
  1567. X          struct leaf *xnode;
  1568. X          D = fopen ("/tmp/DEBUG", "w");
  1569. X          pnt = TrPnt[2];
  1570. X          fprintf (D, "hashfile failure\n");
  1571. X          algbr (PV >> 8, PV & 0x3f, 0);
  1572. X          fprintf (D, "inout move is %s\n", mvstr);
  1573. X          fprintf (D, "legal move are \n");
  1574. X          for (r = TrPnt[ply]; r < TrPnt[ply + 1]; r++)
  1575. X        {
  1576. X          xnode = &Tree[r];
  1577. X          algbr (xnode->f, xnode->t, (short) xnode->flags);
  1578. X          fprintf (D, "%s %s %s %s\n", mvstr[0], mvstr[1], mvstr[2], mvstr[3]);
  1579. X        }
  1580. X          fprintf (D, "\n current board is\n");
  1581. X          for (r = 7; r >= 0; r--)
  1582. X        {
  1583. X          for (c = 0; c <= 7; c++)
  1584. X            {
  1585. X              l = locn (r, c);
  1586. X              if (color[l] == neutral)
  1587. X            fprintf (D, " -");
  1588. X              else if (color[l] == white)
  1589. X            fprintf (D, " %c", qxx[board[l]]);
  1590. X              else
  1591. X            fprintf (D, " %c", pxx[board[l]]);
  1592. X            }
  1593. X          fprintf (D, "\n");
  1594. X        }
  1595. X          fprintf (D, "\n");
  1596. X          fclose (D);
  1597. X        }
  1598. X#endif
  1599. X    }
  1600. X#endif /* HASHFILE */
  1601. X    }
  1602. X
  1603. X#endif /* ttblsz */
  1604. X
  1605. X  /*
  1606. X   * if more then DepthBeyond ply past goal depth or at goal depth and
  1607. X   * score > beta quit - means we are out of the window
  1608. X   */
  1609. X  if (ply > DepthBeyond || (depth < 1 && score > beta))
  1610. X    {
  1611. X      return (score);
  1612. X    }
  1613. X
  1614. X  /*
  1615. X   * if below first ply and not at goal depth generate all moves else only
  1616. X   * capture moves
  1617. X   */
  1618. X  if (ply > 1)
  1619. X    if (depth > 0)
  1620. X      {
  1621. X    MoveList (side, ply);
  1622. X      }
  1623. X    else
  1624. X      CaptureList (side, ply);
  1625. X
  1626. X  /* no moves return what we have */
  1627. X
  1628. X  /*
  1629. X   * normally a search will continue til past goal and no more capture
  1630. X   * moves exist
  1631. X   */
  1632. X  /* unless it hits DepthBeyond */
  1633. X  if (TrPnt[ply] == TrPnt[ply + 1])
  1634. X    {
  1635. X      return (score);
  1636. X    }
  1637. X  cf = (depth < 1 && ply > Sdepth + 1 && !ChkFlag[ply - 2] && !slk);
  1638. X
  1639. X  /* if not at goal set best = -inf else current score */
  1640. X  best = ((depth > 0) ? -12000 : score);
  1641. X  /* if best so far is better than alpha set alpha to best */
  1642. X  if (best > alpha)
  1643. X    alpha = best;
  1644. X  /********************** main loop ************************************************************************/
  1645. X  /* look at each move until no more or beta cutoff */
  1646. X  for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++)
  1647. X    {
  1648. X      /* find the most interesting looking of the remaining moves */
  1649. X      pick (pnt, TrPnt[ply + 1] - 1);
  1650. X
  1651. X      node = &Tree[pnt];
  1652. X      /* is this a forbidden move */
  1653. X      if (ply == 1 && node->score == -32768)
  1654. X    continue;
  1655. X      nxtline[ply + 1] = 0;
  1656. X      if (cf && score + node->score < alpha)
  1657. X    break;
  1658. X#if !defined CHESSTOOL && !defined XBOARD
  1659. X      /* if at top level */
  1660. X      if (ply == 1)
  1661. X    {            /* at the top update search status */
  1662. X      if (flag.post)
  1663. X#ifdef QUIETBACKGROUND
  1664. X        if (!background)
  1665. X#endif /* QUIETBACKGROUND */
  1666. X          ShowCurrentMove (pnt, node->f, node->t);
  1667. X    }
  1668. X#endif
  1669. X      if (!(node->flags & exact))
  1670. X    {
  1671. X      /* make the move and go deeper */
  1672. X      MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  1673. X      CptrFlag[ply] = (node->flags & capture);
  1674. X      PawnThreat[ply] = (node->flags & pwnthrt);
  1675. X      Tscore[ply] = node->score;
  1676. X      PV = node->reply;
  1677. X      node->score = -search (xside, ply + 1,
  1678. X                 ((depth > 0) ? depth - 1 : 0),
  1679. X                 -beta, -alpha,
  1680. X                 nxtline, &rcnt);
  1681. X      node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
  1682. X      if (abs (node->score) > 9000)
  1683. X        node->flags |= exact;
  1684. X      else if (rcnt == 1)
  1685. X        node->score /= 2;
  1686. X      if ((rcnt >= 2 || GameCnt - Game50 > 99 || (node->score == 9999 - ply && !ChkFlag[ply])))
  1687. X        {
  1688. X          node->flags |= (draw | exact);
  1689. X          DRAW = CP[58];    /* Draw */
  1690. X          node->score = ((side == computer) ? contempt : -contempt);
  1691. X        }
  1692. X      node->reply = nxtline[ply + 1];
  1693. X      /* reset to try next move */
  1694. X      UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1695. X    }
  1696. X      /* if best move so far */
  1697. X
  1698. X      if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
  1699. X    {
  1700. X      /* all things being equal pick the denser part of the tree */
  1701. X      bestwidth = node->width;
  1702. X
  1703. X      /*
  1704. X           * if not at goal depth and better than alpha and not an exact
  1705. X           * score increment by depth
  1706. X           */
  1707. X      if (depth > 0 && node->score > alpha && !(node->flags & exact))
  1708. X        node->score += depth;
  1709. X      best = node->score;
  1710. X      pbst = pnt;
  1711. X      if (best > alpha)
  1712. X        {
  1713. X          alpha = best;
  1714. X        }
  1715. X      /* update best line */
  1716. X      for (j = ply + 1; nxtline[j] > 0; j++)
  1717. X        bstline[j] = nxtline[j];
  1718. X      bstline[j] = 0;
  1719. X      bstline[ply] = (node->f << 8) | node->t;
  1720. X      /* if at the top */
  1721. X      if (ply == 1)
  1722. X        {
  1723. X
  1724. X          /*
  1725. X               * if its better than the root score make it the root
  1726. X               */
  1727. X          if ((best > root->score) || ((best == root->score) && (bestwidth > root->width)))
  1728. X        {
  1729. X          tmp = Tree[pnt];
  1730. X          for (j = pnt - 1; j >= 0; j--)
  1731. X            Tree[j + 1] = Tree[j];
  1732. X          Tree[0] = tmp;
  1733. X          pbst = 0;
  1734. X        }
  1735. X#if !defined CHESSTOOL && !defined XBOARD
  1736. X#ifdef QUIETBACKGROUND
  1737. X          if (!background)
  1738. X#endif /* QUIETBACKGROUND */
  1739. X        if (Sdepth > 2)
  1740. X          if (best > beta)
  1741. X            {
  1742. X              ShowResults (best, bstline, '+');
  1743. X            }
  1744. X          else if (best < alpha)
  1745. X            {
  1746. X              ShowResults (best, bstline, '-');
  1747. X            }
  1748. X          else
  1749. X            ShowResults (best, bstline, '&');
  1750. X#endif
  1751. X          restype = (best < alpha) ? false : true;
  1752. X        }
  1753. X    }
  1754. X      if (Sdepth > MINDEPTH && flag.timeout)
  1755. X    {
  1756. X      if (ply == 1)
  1757. X        globalpnt = (pnt);
  1758. X      return (Tscore[ply]);
  1759. X    }
  1760. X    }
  1761. X
  1762. X  /******************************************************************************************/
  1763. X  globalpnt = (pnt);
  1764. X  node = &Tree[pbst];
  1765. X  mv = (node->f << 8) | node->t;
  1766. X
  1767. X  /*
  1768. X   * we have a move so put it in local table - if it's already there done
  1769. X   * else if not there or needs to be updated also put it in hashfile
  1770. X   */
  1771. X#if ttblsz
  1772. X  if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  1773. X    {
  1774. X      if (PutInTTable (side, best, depth, ply, alpha, beta, mv)
  1775. X#ifdef HASHFILE
  1776. X      && hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit))
  1777. X    {
  1778. X      PutInFTable (side, best, depth, ply, alpha, beta, node->f, node->t);
  1779. X    }
  1780. X#else
  1781. X    );
  1782. X#endif /* HASHFILE */
  1783. X    }
  1784. X
  1785. X#endif /* ttblsz */
  1786. X  if (depth > 0)
  1787. X    {
  1788. X#if !defined NOHISTORY
  1789. X      j = (node->f << 6) | node->t;
  1790. X      if (side == black)
  1791. X    j |= 0x1000;
  1792. X      if (history[j] < 150)
  1793. X    history[j] += (unsigned char) depth << 1;
  1794. X#endif
  1795. X      if (node->t != (GameList[GameCnt].gmove & 0xFF))
  1796. X    if (best <= beta)
  1797. X      killr3[ply] = mv;
  1798. X    else if (mv != killr1[ply])
  1799. X      {
  1800. X        killr2[ply] = killr1[ply];
  1801. X        killr1[ply] = mv;
  1802. X      }
  1803. X      killr0[ply] = ((best > 9000) ? mv : 0);
  1804. X    }
  1805. X
  1806. X  return (best);
  1807. X}
  1808. X
  1809. X
  1810. X
  1811. X
  1812. Xint
  1813. Xcastle (short int side, short int kf, short int kt, short int iop)
  1814. X
  1815. X/* Make or Unmake a castling move. */
  1816. X
  1817. X{
  1818. X  register short rf, rt, t0, xside;
  1819. X
  1820. X  xside = side ^ 1;
  1821. X  if (kt > kf)
  1822. X    {
  1823. X      rf = kf + 3;
  1824. X      rt = kt - 1;
  1825. X    }
  1826. X  else
  1827. X    {
  1828. X      rf = kf - 4;
  1829. X      rt = kt + 1;
  1830. X    }
  1831. X  if (iop == 0)
  1832. X    {
  1833. X      if (kf != kingP[side] ||
  1834. X      board[kf] != king ||
  1835. X      board[rf] != rook ||
  1836. X      color[kf] != side ||
  1837. X      color[rf] != side ||
  1838. X      Mvboard[kf] != 0 ||
  1839. X      Mvboard[rf] != 0 ||
  1840. X      color[kt] != neutral ||
  1841. X      color[rt] != neutral ||
  1842. X      color[kt - 1] != neutral ||
  1843. X      SqAtakd (kf, xside) ||
  1844. X      SqAtakd (kt, xside) ||
  1845. X      SqAtakd (rt, xside))
  1846. X    return (false);
  1847. X    }
  1848. X  else
  1849. X    {
  1850. X      if (iop == 1)
  1851. X    {
  1852. X      castld[side] = true;
  1853. X      Mvboard[kf]++;
  1854. X      Mvboard[rf]++;
  1855. X    }
  1856. X      else
  1857. X    {
  1858. X      castld[side] = false;
  1859. X      Mvboard[kf]--;
  1860. X      Mvboard[rf]--;
  1861. X      t0 = kt;
  1862. X      kt = kf;
  1863. X      kf = t0;
  1864. X      t0 = rt;
  1865. X      rt = rf;
  1866. X      rf = t0;
  1867. X    }
  1868. X      board[kt] = king;
  1869. X      color[rt] = color[kt] = side;
  1870. X      Pindex[kt] = 0;
  1871. X      board[kf] = no_piece;
  1872. X      color[rf] = color[kf] = neutral;
  1873. X      board[rt] = rook;
  1874. X      Pindex[rt] = Pindex[rf];
  1875. X      board[rf] = no_piece;
  1876. X      PieceList[side][Pindex[kt]] = kt;
  1877. X      PieceList[side][Pindex[rt]] = rt;
  1878. X      UpdateHashbd (side, king, kf, kt);
  1879. X      UpdateHashbd (side, rook, rf, rt);
  1880. X    }
  1881. X  return (true);
  1882. X}
  1883. X
  1884. X
  1885. Xvoid
  1886. XEnPassant (short int xside, short int f, short int t, short int iop)
  1887. X
  1888. X/*
  1889. X * Make or unmake an en passant move.
  1890. X */
  1891. X
  1892. X{
  1893. X  register short l;
  1894. X
  1895. X  l = t + ((t > f) ? -8 : 8);
  1896. X  if (iop == 1)
  1897. X    {
  1898. X      board[l] = no_piece;
  1899. X      color[l] = neutral;
  1900. X    }
  1901. X  else
  1902. X    {
  1903. X      board[l] = pawn;
  1904. X      color[l] = xside;
  1905. X    }
  1906. X  InitializeStats ();
  1907. X  if (iop != 1)
  1908. X    epsquare = t;
  1909. X}
  1910. X
  1911. X
  1912. Xvoid
  1913. XUpdatePieceList (short int side, short int sq, short int iop)
  1914. X
  1915. X/*
  1916. X * Update the PieceList and Pindex arrays when a piece is captured or when a
  1917. X * capture is unmade.
  1918. X */
  1919. X
  1920. X{
  1921. X  register short i;
  1922. X
  1923. X  if (iop == 1)
  1924. X    {
  1925. X      PieceCnt[side]--;
  1926. X      for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1927. X    {
  1928. X      PieceList[side][i] = PieceList[side][i + 1];
  1929. X      Pindex[PieceList[side][i]] = i;
  1930. X    }
  1931. X    }
  1932. X  else
  1933. X    {
  1934. X      PieceCnt[side]++;
  1935. X      PieceList[side][PieceCnt[side]] = sq;
  1936. X      Pindex[sq] = PieceCnt[side];
  1937. X    }
  1938. X}
  1939. X
  1940. Xvoid
  1941. XMakeMove (short int side,
  1942. X      struct leaf * node,
  1943. X      short int *tempb,    /* color of to square */
  1944. X      short int *tempc,    /* piece at to square */
  1945. X      short int *tempsf,    /* static value of piece on from */
  1946. X      short int *tempst,    /* static value of piece on to */
  1947. X      short int *INCscore)    /* score increment for pawn structure change */
  1948. X
  1949. X/*
  1950. X * Update Arrays board[], color[], and Pindex[] to reflect the new board
  1951. X * position obtained after making the move pointed to by node. Also update
  1952. X * miscellaneous stuff that changes when a move is made.
  1953. X */
  1954. X
  1955. X{
  1956. X  register short f, t, xside, ct, cf;
  1957. X  register struct GameRec *g;
  1958. X
  1959. X  xside = side ^ 1;
  1960. X  g = &GameList[++GameCnt];
  1961. X  g->hashkey = hashkey;
  1962. X  g->hashbd = hashbd;
  1963. X  f = node->f;
  1964. X  t = node->t;
  1965. X  epsquare = -1;
  1966. X  FROMsquare = f;
  1967. X  TOsquare = t;
  1968. X  *INCscore = 0;
  1969. X  g->Game50 = Game50;
  1970. X  g->gmove = (f << 8) | t;
  1971. X  g->flags = node->flags;
  1972. X  if (node->flags & cstlmask)
  1973. X    {
  1974. X      g->piece = no_piece;
  1975. X      g->color = side;
  1976. X      (void) castle (side, f, t, 1);
  1977. X      Game50 = GameCnt;
  1978. X    }
  1979. X  else
  1980. X    {
  1981. X      if (!(node->flags & capture) && (board[f] != pawn))
  1982. X    rpthash[side][hashkey & 0xFF]++;
  1983. X      else
  1984. X    Game50 = GameCnt;
  1985. X      *tempsf = svalue[f];
  1986. X      *tempst = svalue[t];
  1987. X      g->piece = *tempb = board[t];
  1988. X      g->color = *tempc = color[t];
  1989. X      if (*tempc != neutral)
  1990. X    {
  1991. X      UpdatePieceList (*tempc, t, 1);
  1992. X      /* if capture decrement pawn count */
  1993. X      if (*tempb == pawn)
  1994. X        {
  1995. X          --PawnCnt[*tempc][column (t)];
  1996. X        }
  1997. X      if (board[f] == pawn)
  1998. X        {
  1999. X          cf = column (f);
  2000. X          ct = column (t);
  2001. X          /* move count from from to to */
  2002. X          --PawnCnt[side][cf];
  2003. X          ++PawnCnt[side][ct];
  2004. X
  2005. X          /*
  2006. X               * calculate increment for pawn structure changes
  2007. X               */
  2008. X          /* doubled or more - */
  2009. X          if (PawnCnt[side][ct] > (1 + PawnCnt[side][cf]))
  2010. X        *INCscore -= 15;
  2011. X          /* went to empty column + */
  2012. X          else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  2013. X        *INCscore += 15;
  2014. X
  2015. X          /*
  2016. X               * went to outside col or empty col on one side ????????
  2017. X               */
  2018. X          else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  2019. X        *INCscore -= 15;
  2020. X        }
  2021. X      mtl[xside] -= value[*tempb];
  2022. X      if (*tempb == pawn)
  2023. X        pmtl[xside] -= valueP;
  2024. X      UpdateHashbd (xside, *tempb, -1, t);
  2025. X      *INCscore += *tempst;
  2026. X      Mvboard[t]++;
  2027. X    }
  2028. X      color[t] = color[f];
  2029. X      board[t] = board[f];
  2030. X      svalue[t] = svalue[f];
  2031. X      Pindex[t] = Pindex[f];
  2032. X      PieceList[side][Pindex[t]] = t;
  2033. X      color[f] = neutral;
  2034. X      board[f] = no_piece;
  2035. X      if (board[t] == pawn)
  2036. X    if (t - f == 16)
  2037. X      epsquare = f + 8;
  2038. X    else if (f - t == 16)
  2039. X      epsquare = f - 8;
  2040. X      if (node->flags & promote)
  2041. X    {
  2042. X      board[t] = node->flags & pmask;
  2043. X      if (board[t] == queen)
  2044. X        HasQueen[side]++;
  2045. X      else if (board[t] == rook)
  2046. X        HasRook[side]++;
  2047. X      else if (board[t] == bishop)
  2048. X        HasBishop[side]++;
  2049. X      else if (board[t] == knight)
  2050. X        HasKnight[side]++;
  2051. X      --PawnCnt[side][column (t)];
  2052. X      mtl[side] += value[board[t]] - valueP;
  2053. X      pmtl[side] -= valueP;
  2054. X      UpdateHashbd (side, pawn, f, -1);
  2055. X      UpdateHashbd (side, board[t], f, -1);
  2056. X      *INCscore -= *tempsf;
  2057. X    }
  2058. X      if (node->flags & epmask)
  2059. X    EnPassant (xside, f, t, 1);
  2060. X      else
  2061. X    UpdateHashbd (side, board[t], f, t);
  2062. X      Mvboard[f]++;
  2063. X    }
  2064. X}
  2065. X
  2066. Xvoid
  2067. XUnmakeMove (short int side,
  2068. X        struct leaf * node,
  2069. X        short int *tempb,
  2070. X        short int *tempc,
  2071. X        short int *tempsf,
  2072. X        short int *tempst)
  2073. X
  2074. X/*
  2075. X * Take back a move.
  2076. X */
  2077. X
  2078. X{
  2079. X  register short f, t, xside;
  2080. X
  2081. X  xside = side ^ 1;
  2082. X  f = node->f;
  2083. X  t = node->t;
  2084. X  epsquare = -1;
  2085. X  Game50 = GameList[GameCnt--].Game50;
  2086. X  if (node->flags & cstlmask)
  2087. X    (void) castle (side, f, t, 2);
  2088. X  else
  2089. X    {
  2090. X      color[f] = color[t];
  2091. X      board[f] = board[t];
  2092. X      svalue[f] = *tempsf;
  2093. X      Pindex[f] = Pindex[t];
  2094. X      PieceList[side][Pindex[f]] = f;
  2095. X      color[t] = *tempc;
  2096. X      board[t] = *tempb;
  2097. X      svalue[t] = *tempst;
  2098. X      if (node->flags & promote)
  2099. X    {
  2100. X      board[f] = pawn;
  2101. X      ++PawnCnt[side][column (t)];
  2102. X      mtl[side] += valueP - value[node->flags & pmask];
  2103. X      pmtl[side] += valueP;
  2104. X      UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  2105. X      UpdateHashbd (side, pawn, -1, t);
  2106. X    }
  2107. X      if (*tempc != neutral)
  2108. X    {
  2109. X      UpdatePieceList (*tempc, t, 2);
  2110. X      if (*tempb == pawn)
  2111. X        {
  2112. X          ++PawnCnt[*tempc][column (t)];
  2113. X        }
  2114. X      if (board[f] == pawn)
  2115. X        {
  2116. X          --PawnCnt[side][column (t)];
  2117. X          ++PawnCnt[side][column (f)];
  2118. X        }
  2119. X      mtl[xside] += value[*tempb];
  2120. X      if (*tempb == pawn)
  2121. X        pmtl[xside] += valueP;
  2122. X      UpdateHashbd (xside, *tempb, -1, t);
  2123. X      Mvboard[t]--;
  2124. X    }
  2125. X      if (node->flags & epmask)
  2126. X    EnPassant (xside, f, t, 2);
  2127. X      else
  2128. X    UpdateHashbd (side, board[f], f, t);
  2129. X      Mvboard[f]--;
  2130. X      if (!(node->flags & capture) && (board[f] != pawn))
  2131. X    rpthash[side][hashkey & 0xFF]--;
  2132. X    }
  2133. X}
  2134. X
  2135. X
  2136. Xvoid
  2137. XInitializeStats (void)
  2138. X
  2139. X/*
  2140. X * Scan thru the board seeing what's on each square. If a piece is found,
  2141. X * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  2142. X * determine the material for each side and set the hashkey and hashbd
  2143. X * variables to represent the current board position. Array
  2144. X * PieceList[side][indx] contains the location of all the pieces of either
  2145. X * side. Array Pindex[sq] contains the indx into PieceList for a given
  2146. X * square.
  2147. X */
  2148. X
  2149. X{
  2150. X  register short i, sq;
  2151. X
  2152. X  epsquare = -1;
  2153. X  for (i = 0; i < 8; i++)
  2154. X    {
  2155. X      PawnCnt[white][i] = PawnCnt[black][i] = 0;
  2156. X    }
  2157. X  mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  2158. X  PieceCnt[white] = PieceCnt[black] = 0;
  2159. X  hashbd = hashkey = 0;
  2160. X  for (sq = 0; sq < 64; sq++)
  2161. X    if (color[sq] != neutral)
  2162. X      {
  2163. X    mtl[color[sq]] += value[board[sq]];
  2164. X    if (board[sq] == pawn)
  2165. X      {
  2166. X        pmtl[color[sq]] += valueP;
  2167. X        ++PawnCnt[color[sq]][column (sq)];
  2168. X      }
  2169. X    Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
  2170. X
  2171. X    PieceList[color[sq]][Pindex[sq]] = sq;
  2172. X    hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  2173. X    hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  2174. X      }
  2175. X}
  2176. END_OF_FILE
  2177. if test 32814 -ne `wc -c <'src/search.c'`; then
  2178.     echo shar: \"'src/search.c'\" unpacked with wrong size!
  2179. fi
  2180. # end of 'src/search.c'
  2181. fi
  2182. echo shar: End of archive 4 \(of 12\).
  2183. cp /dev/null ark4isdone
  2184. MISSING=""
  2185. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  2186.     if test ! -f ark${I}isdone ; then
  2187.     MISSING="${MISSING} ${I}"
  2188.     fi
  2189. done
  2190. if test "${MISSING}" = "" ; then
  2191.     echo You have unpacked all 12 archives.
  2192.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2193.     echo Building book file.
  2194.     cat misc/book.xaa misc/book.xab > misc/gnuchess.nunn.book
  2195.     rm misc/book.xaa misc/book.xab
  2196. else
  2197.     echo You still need to unpack the following archives:
  2198.     echo "        " ${MISSING}
  2199. fi
  2200. ##  End of shell archive.
  2201. exit 0
  2202.