home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / gnuchess.lzh / gnuchess.4 < prev    next >
Text File  |  1991-05-19  |  51KB  |  2,268 lines

  1.  
  2. #!/bin/sh
  3. # do not concatenate these parts, unpack them in order with /bin/sh
  4. # file gnuchess.c continued
  5. #
  6. if test ! -r _shar_seq_.tmp; then
  7.     echo 'Please unpack part 1 first!'
  8.     exit 1
  9. fi
  10. (read Scheck
  11.  if test "$Scheck" != 4; then
  12.     echo Please unpack part "$Scheck" next!
  13.     exit 1
  14.  else
  15.     exit 0
  16.  fi
  17. ) < _shar_seq_.tmp || exit 1
  18. if test ! -f _shar_wnt_.tmp; then
  19.     echo 'x - still skipping gnuchess.c'
  20. else
  21. echo 'x - continuing file gnuchess.c'
  22. sed 's/^X//' << 'SHAR_EOF' >> 'gnuchess.c' &&
  23. X    {
  24. X      root->flags |= draw;
  25. X      DRAW = "No moves";
  26. X    }
  27. X  if (iop == 2)
  28. X    return;
  29. X  if (Book == NULL)
  30. X    hint = PrVar[2];
  31. X  ElapsedTime (1);
  32. X
  33. X  if (score > -9999 && rpt <= 2)
  34. X    {
  35. X      MakeMove (side, root, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  36. X      algbr (root->f, root->t, (short) root->flags);
  37. X    }
  38. X  else
  39. X    algbr (0, 0, 0);
  40. X  OutputMove ();
  41. X  if (score == -9999 || score == 9998)
  42. X    flag.mate = true;
  43. X  if (flag.mate)
  44. X    hint = 0;
  45. X  if ((board[root->t] == pawn) || (root->flags & (capture | cstlmask)))
  46. X    {
  47. X      Game50 = GameCnt;
  48. X      ZeroRPT ();
  49. X    }
  50. X  g = &GameList[GameCnt];
  51. X  g->score = score;
  52. X  g->nodes = NodeCnt;
  53. X  g->time = (short) et;
  54. X  g->depth = Sdepth;
  55. X  g->flags = root->flags;
  56. X  if (TCflag)
  57. X    {
  58. X      TimeControl.clock[side] -= (et + OperatorTime);
  59. X      if (--TimeControl.moves[side] == 0)
  60. X    SetTimeControl ();
  61. X    }
  62. X  if ((root->flags & draw) && flag.bothsides)
  63. X    flag.mate = true;
  64. X  if (GameCnt > 190)
  65. X    flag.mate = true;        /* out of move store, you loose */
  66. X  player = xside;
  67. X  Sdepth = 0;
  68. X  fflush (stdin);
  69. }
  70. X
  71. int
  72. parse (FILE * fd, short unsigned int *mv, short int side)
  73. {
  74. X  int c, i, r1, r2, c1, c2;
  75. X  char s[100];
  76. X  while ((c = getc (fd)) == ' ') ;
  77. X  i = 0;
  78. X  s[0] = (char) c;
  79. X  while (c != ' ' && c != '\n' && c != EOF)
  80. X    s[++i] = (char) (c = getc (fd));
  81. X  s[++i] = '\0';
  82. X  if (c == EOF)
  83. X    return (-1);
  84. X  if (s[0] == '!' || s[0] == ';' || i < 3)
  85. X    {
  86. X      while (c != '\n' && c != EOF)
  87. X    c = getc (fd);
  88. X      return (0);
  89. X    }
  90. X  if (s[4] == 'o')
  91. X    *mv = (side == black) ? 0x3C3A : 0x0402;
  92. X  else if (s[0] == 'o')
  93. X    *mv = (side == black) ? 0x3C3E : 0x0406;
  94. X  else
  95. X    {
  96. X      c1 = s[0] - 'a';
  97. X      r1 = s[1] - '1';
  98. X      c2 = s[2] - 'a';
  99. X      r2 = s[3] - '1';
  100. X      *mv = (locn (r1, c1) << 8) | locn (r2, c2);
  101. X    }
  102. X  return (1);
  103. }
  104. X
  105. void
  106. GetOpenings (void)
  107. X
  108. /*
  109. X   Read in the Opening Book file and parse the algebraic notation for a move
  110. X   into an unsigned integer format indicating the from and to square. Create
  111. X   a linked list of opening lines of play, with entry->next pointing to the
  112. X   next line and entry->move pointing to a chunk of memory containing the
  113. X   moves. More Opening lines of up to 256 half moves may be added to
  114. X   gnuchess.book.
  115. */
  116. #ifndef BOOK
  117. #define BOOK "/usr/games/lib/gnuchess.book"
  118. #endif /* BOOK */
  119. {
  120. X  FILE *fd;
  121. X  int c, i, j, side;
  122. X  /* char buffr[2048]; */
  123. X  struct BookEntry *entry;
  124. X  unsigned short mv, *mp, tmp[100];
  125. X
  126. X  if ((fd = fopen (BOOK, "r")) == NULL)
  127. X    fd = fopen ("gnuchess.book", "r");
  128. X  if (fd != NULL)
  129. X    {
  130. X      /* setvbuf(fd,buffr,_IOFBF,2048); */
  131. X      Book = NULL;
  132. X      i = 0;
  133. X      side = white;
  134. X      while ((c = parse (fd, &mv, side)) >= 0)
  135. X    if (c == 1)
  136. X      {
  137. X        tmp[++i] = mv;
  138. X        side = otherside[side];
  139. X      }
  140. X    else if (c == 0 && i > 0)
  141. X      {
  142. X        entry = (struct BookEntry *) malloc (sizeof (struct BookEntry));
  143. X        mp = (unsigned short *) malloc ((i + 1) * sizeof (unsigned short));
  144. X        if (!entry || !mp)
  145. X          {
  146. X        Book = NULL;
  147. X        ShowMessage ("warning: can't load book, out of memory.");
  148. X        return;
  149. X          }
  150. X        entry->mv = mp;
  151. X        entry->next = Book;
  152. X        Book = entry;
  153. X        for (j = 1; j <= i; j++)
  154. X          *(mp++) = tmp[j];
  155. X        *mp = 0;
  156. X        i = 0;
  157. X        side = white;
  158. X      }
  159. X      fclose (fd);
  160. X      BKBook = Book;
  161. X    }
  162. X  else
  163. X    ShowMessage ("warning: can't find book.");
  164. }
  165. X
  166. X
  167. void
  168. OpeningBook (unsigned short *hint)
  169. X
  170. /*
  171. X  Go thru each of the opening lines of play and check for a match with the
  172. X  current game listing. If a match occurs, generate a random number. If this
  173. X  number is the largest generated so far then the next move in this line
  174. X  becomes the current "candidate". After all lines are checked, the
  175. X  candidate move is put at the top of the Tree[] array and will be played by
  176. X  the program. Note that the program does not handle book transpositions.
  177. */
  178. X
  179. {
  180. X  short j, pnt;
  181. X  unsigned short m, *mp;
  182. X  unsigned r, r0;
  183. X  struct BookEntry *p;
  184. X
  185. X  srand ((unsigned int) time ((long *) 0));
  186. X  r0 = m = 0;
  187. X  p = Book;
  188. X  while (p != NULL)
  189. X    {
  190. X      mp = p->mv;
  191. X      for (j = 1; j <= GameCnt; j++)
  192. X    if (GameList[j].gmove != *(mp++))
  193. X      break;
  194. X      if (j > GameCnt)
  195. X    if ((r = urand ()) > r0)
  196. X      {
  197. X        r0 = r;
  198. X        m = *mp;
  199. X        *hint = *(++mp);
  200. X      }
  201. X      p = p->next;
  202. X    }
  203. X
  204. X  for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
  205. X    if (((Tree[pnt].f << 8) | Tree[pnt].t) == m)
  206. X      Tree[pnt].score = 0;
  207. X  pick (TrPnt[1], TrPnt[2] - 1);
  208. X  if (Tree[TrPnt[1]].score < 0)
  209. X    Book = NULL;
  210. }
  211. X
  212. X
  213. inline void
  214. repetition (short int *cnt)
  215. X
  216. /*
  217. X  Check for draw by threefold repetition.
  218. */
  219. X
  220. {
  221. X  register short i, c, f, t;
  222. X  short b[64];
  223. X  unsigned short m;
  224. X
  225. X  *cnt = c = 0;
  226. X  if (GameCnt > Game50 + 3)
  227. X    {
  228. #ifdef NOMEMSET
  229. X      for (i = 0; i < 64; b[i++] = 0) ;
  230. #else
  231. X      memset ((char *) b, 0, sizeof (b));
  232. #endif /* NOMEMSET */
  233. X      for (i = GameCnt; i > Game50; i--)
  234. X    {
  235. X      m = GameList[i].gmove;
  236. X      f = m >> 8;
  237. X      t = m & 0xFF;
  238. X      if (++b[f] == 0)
  239. X        c--;
  240. X      else
  241. X        c++;
  242. X      if (--b[t] == 0)
  243. X        c--;
  244. X      else
  245. X        c++;
  246. X      if (c == 0)
  247. X        (*cnt)++;
  248. X    }
  249. X    }
  250. }
  251. X
  252. X
  253. int
  254. search (short int side,
  255. X    short int ply,
  256. X    short int depth,
  257. X    short int alpha,
  258. X    short int beta,
  259. X    short unsigned int *bstline,
  260. X    short int *rpt)
  261. X
  262. /*
  263. X   Perform an alpha-beta search to determine the score for the current board
  264. X   position. If depth <= 0 only capturing moves, pawn promotions and
  265. X   responses to check are generated and searched, otherwise all moves are
  266. X   processed. The search depth is modified for check evasions, certain
  267. X   re-captures and threats. Extensions may continue for up to 11 ply beyond
  268. X   the nominal search depth.
  269. X */
  270. X
  271. #define UpdateSearchStatus \
  272. {\
  273. X   if (flag.post) ShowCurrentMove(pnt,node->f,node->t);\
  274. X     if (pnt > TrPnt[1])\
  275. X       {\
  276. X      d = best-Zscore; e = best-node->score;\
  277. X        if (best < alpha) ExtraTime = 10*ResponseTime;\
  278. X        else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
  279. X        else if (d > -zwndw) ExtraTime = 0;\
  280. X        else if (d > -3*zwndw) ExtraTime = ResponseTime;\
  281. X        else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
  282. X        else ExtraTime = 5*ResponseTime;\
  283. X        }\
  284. X        }
  285. #define prune (cf && score+node->score < alpha)
  286. #define ReCapture (flag.rcptr && score > alpha && score < beta &&\
  287. X           ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
  288. /* && depth == Sdepth-ply+1 */
  289. #define Parry (hung[side] > 1 && ply == Sdepth+1)
  290. #define MateThreat (ply < Sdepth+4 && ply > 4 &&\
  291. X            ChkFlag[ply-2] && ChkFlag[ply-4] &&\
  292. X            ChkFlag[ply-2] != ChkFlag[ply-4])
  293. X
  294. {
  295. X  register short j, pnt;
  296. X  short best, tempb, tempc, tempsf, tempst;
  297. X  short xside, pbst, d, e, cf, score, rcnt, slk, InChk;
  298. X  unsigned short mv, nxtline[maxdepth];
  299. X  struct leaf *node, tmp;
  300. X
  301. X  NodeCnt++;
  302. X  xside = otherside[side];
  303. X
  304. X  if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  305. X    repetition (rpt);
  306. X  else
  307. X    *rpt = 0;
  308. X  /* Detect repetitions a bit earlier. SMC. 12/89 */
  309. X  if (*rpt == 1 && ply > 1)
  310. X    return (0);
  311. X  /* if (*rpt >= 2) return(0); */
  312. X  /* slk is lone king indicator for either side */
  313. X  score = evaluate (side, ply, alpha, beta, INCscore, &slk, &InChk);
  314. X  if (score > 9000)
  315. X    {
  316. X      bstline[ply] = 0;
  317. X      return (score);
  318. X    }
  319. X  if (depth > 0)
  320. X    {
  321. X      /* Allow opponent a chance to check again */
  322. X      if (InChk)
  323. X    depth = (depth < 2) ? 2 : depth;
  324. X      else if (PawnThreat[ply - 1] || ReCapture)
  325. X    ++depth;
  326. X    }
  327. X  else
  328. X    {
  329. X      if (score >= alpha && (InChk || PawnThreat[ply - 1] || Parry))
  330. X    depth = 1;
  331. X      else if (score <= beta && MateThreat)
  332. X    depth = 1;
  333. X    }
  334. X
  335. #if ttblsz
  336. X  if (depth > 0 && flag.hash && ply > 1)
  337. X    {
  338. X      if (ProbeTTable (side, depth, &alpha, &beta, &score) == true)
  339. X    {
  340. X      bstline[ply] = PV;
  341. X      bstline[ply + 1] = 0;
  342. X      if (beta == -20000)
  343. X        return (score);
  344. X      if (alpha > beta)
  345. X        return (alpha);
  346. X    }
  347. #ifdef HASHFILE
  348. X      else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  349. X           && (ProbeFTable (side, depth, &alpha, &beta, &score) == true))
  350. X    {
  351. X      PutInTTable (side, score, depth, alpha, beta, PV);
  352. X      bstline[ply] = PV;
  353. X      bstline[ply + 1] = 0;
  354. X      if (beta == -20000)
  355. X        return (score);
  356. X      if (alpha > beta)
  357. X        return (alpha);
  358. X    }
  359. #endif /* HASHFILE */
  360. X    }
  361. #endif /* ttblsz */
  362. X  d = (Sdepth == 1) ? 7 : 11;
  363. X  if (ply > Sdepth + d || (depth < 1 && score > beta))
  364. X    return (score);        /* score >= beta ?? */
  365. X
  366. X  if (ply > 1)
  367. X    if (depth > 0)
  368. X      MoveList (side, ply);
  369. X    else
  370. X      CaptureList (side, ply);
  371. X
  372. X  if (TrPnt[ply] == TrPnt[ply + 1])
  373. X    return (score);
  374. X
  375. X  cf = (depth < 1 && ply > Sdepth + 1 && !ChkFlag[ply - 2] && !slk);
  376. X
  377. X  best = (depth > 0) ? -12000 : score;
  378. X  if (best > alpha)
  379. X    alpha = best;
  380. X  /* look at each move until no more or beta cutoff */
  381. X  for (pnt = pbst = TrPnt[ply];
  382. X       pnt < TrPnt[ply + 1] && best < beta;    /* best < beta ?? */
  383. X       pnt++)
  384. X    {
  385. X      /* find the most interesting looking of the remaining moves */
  386. X      if (ply > 1)
  387. X    pick (pnt, TrPnt[ply + 1] - 1);
  388. X      node = &Tree[pnt];
  389. X      mv = (node->f << 8) | node->t;
  390. X      nxtline[ply + 1] = 0;
  391. X      if (prune)
  392. X    break;            /* alpha cutoff */
  393. X      if (ply == 1)
  394. X    UpdateSearchStatus;
  395. X
  396. X      if (!(node->flags & exact))
  397. X    {
  398. X      /* make the move and go deeper */
  399. X      MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  400. X      CptrFlag[ply] = (node->flags & capture);
  401. X      PawnThreat[ply] = (node->flags & pwnthrt);
  402. X      Tscore[ply] = node->score;
  403. X      PV = node->reply;
  404. X      node->score = -search (xside, ply + 1,
  405. X                 (depth > 0) ? depth - 1 : 0,
  406. X                 -beta, -alpha,
  407. X                 nxtline, &rcnt);
  408. X      if (abs (node->score) > 9000)
  409. X        node->flags |= exact;
  410. X      else if (rcnt == 1)
  411. X        node->score /= 2;
  412. X      /* but why doesnt this detect draws??? */
  413. X      if (rcnt >= 2 || GameCnt - Game50 > 99 ||
  414. X          (node->score == 9999 - ply && !ChkFlag[ply]))
  415. X        {
  416. X          node->flags |= (draw | exact);
  417. X          DRAW = "";
  418. X          node->score = (side == computer) ? contempt : -contempt;
  419. X        }
  420. X      node->reply = nxtline[ply + 1];
  421. X      /* reset to try next move */
  422. X      UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  423. X    }
  424. X      if (node->score > best && !flag.timeout)
  425. X    {
  426. X      if (depth > 0 && node->score > alpha && !(node->flags & exact))
  427. X        node->score += depth;
  428. X      best = node->score;
  429. X      pbst = pnt;
  430. X      if (best > alpha)
  431. X        alpha = best;
  432. X      for (j = ply + 1; nxtline[j] > 0; j++)
  433. X        bstline[j] = nxtline[j];
  434. X      bstline[j] = 0;
  435. X      bstline[ply] = mv;
  436. #ifdef DEBUG
  437. X          if(ply == 1)
  438. X        ShowDBLine ("IS", ply, depth, alpha, beta, score, &bstline[ply-1]);
  439. #endif /*DEBUG*/
  440. X      if (ply == 1)
  441. X        {
  442. X          if (best > root->score)
  443. X        {
  444. X          tmp = Tree[pnt];
  445. X          for (j = pnt - 1; j >= 0; j--)
  446. X            Tree[j + 1] = Tree[j];
  447. X          Tree[0] = tmp;
  448. X          pbst = 0;
  449. X        }
  450. X          if (Sdepth > 2)
  451. X        if (best > beta)
  452. X          ShowResults (best, bstline, '+');
  453. X        else if (best < alpha)
  454. X          ShowResults (best, bstline, '-');
  455. X        else
  456. X          ShowResults (best, bstline, '&');
  457. X        }
  458. X    }
  459. X      if (NodeCnt > ETnodes)
  460. X    ElapsedTime (0);
  461. X      if (flag.timeout)
  462. X    return (-Tscore[ply - 1]);
  463. X    }
  464. X
  465. X  node = &Tree[pbst];
  466. X  mv = (node->f << 8) | node->t;
  467. #if ttblsz
  468. X  if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  469. X    {
  470. X      if (PutInTTable (side, best, depth, alpha, beta, mv)
  471. #ifdef HASHFILE
  472. X      && hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit))
  473. X    {
  474. X      PutInFTable (side, best, depth, alpha, beta, node->f, node->t);
  475. X    }
  476. #else
  477. X    );
  478. #endif /* HASHFILE */
  479. X    }
  480. #endif /* ttblsz */
  481. X  if (depth > 0)
  482. X    {
  483. X      j = (node->f << 6) | node->t;
  484. X      if (side == black)
  485. X    j |= 0x1000;
  486. X      if (history[j] < 150)
  487. X    history[j] += (unsigned char) 2 *depth;
  488. X
  489. X      if (node->t != (GameList[GameCnt].gmove & 0xFF))
  490. X    if (best <= beta)
  491. X      killr3[ply] = mv;
  492. X    else if (mv != killr1[ply])
  493. X      {
  494. X        killr2[ply] = killr1[ply];
  495. X        killr1[ply] = mv;
  496. X      }
  497. X      if (best > 9000)
  498. X    killr0[ply] = mv;
  499. X      else
  500. X    killr0[ply] = 0;
  501. X    }
  502. X  return (best);
  503. }
  504. X
  505. #if ttblsz
  506. /*
  507. X  hashbd contains a 32 bit "signature" of the board position. hashkey
  508. X  contains a 16 bit code used to address the hash table. When a move is
  509. X  made, XOR'ing the hashcode of moved piece on the from and to squares with
  510. X  the hashbd and hashkey values keeps things current.
  511. */
  512. #define UpdateHashbd(side, piece, f, t) \
  513. {\
  514. X  if ((f) >= 0)\
  515. X    {\
  516. X      hashbd ^= hashcode[side][piece][f].bd;\
  517. X      hashkey ^= hashcode[side][piece][f].key;\
  518. X    }\
  519. X  if ((t) >= 0)\
  520. X    {\
  521. X      hashbd ^= hashcode[side][piece][t].bd;\
  522. X      hashkey ^= hashcode[side][piece][t].key;\
  523. X    }\
  524. }
  525. X
  526. #define CB(i) (unsigned char) ((color[2 * (i)] ? 0x80 : 0)\
  527. X           | (board[2 * (i)] << 4)\
  528. X           | (color[2 * (i) + 1] ? 0x8 : 0)\
  529. X           | (board[2 * (i) + 1]))
  530. X
  531. int
  532. ProbeTTable (short int side,
  533. X         short int depth,
  534. X         short int *alpha,
  535. X         short int *beta,
  536. X         short int *score)
  537. X
  538. /*
  539. X  Look for the current board position in the transposition table.
  540. */
  541. X
  542. {
  543. X  register struct hashentry *ptbl;
  544. X  register unsigned short i;
  545. X
  546. X  ptbl = &ttable[side][hashkey & (ttblsz - 1)];
  547. X
  548. X  /* rehash max rehash times */
  549. X  for (i = 1; ptbl->hashbd != hashbd && i <= rehash; i++)
  550. X    ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)];
  551. X  if ((short) ptbl->depth >= depth && ptbl->hashbd == hashbd)
  552. X    {
  553. X      HashCnt++;
  554. #ifdef HASHTEST
  555. X      for (i = 0; i < 32; i++)
  556. X    {
  557. X      if (ptbl->bd[i] != CB (i))
  558. X        {
  559. X          HashCol++;
  560. X          ShowMessage ("ttable collision detected");
  561. X          break;
  562. X        }
  563. X    }
  564. #endif /* HASHTEST */
  565. X
  566. X      PV = ptbl->mv;
  567. X      if (ptbl->flags & truescore)
  568. X    {
  569. X      *score = ptbl->score;
  570. X      *beta = -20000;
  571. X    }
  572. #if 0                /* commented out, why? */
  573. X      else if (ptbl->flags & upperbound)
  574. X    {
  575. X      if (ptbl->score < *beta)
  576. X        *beta = ptbl->score + 1;
  577. X    }
  578. #endif
  579. X      else if (ptbl->flags & lowerbound)
  580. X    {
  581. X      if (ptbl->score > *alpha)
  582. X        *alpha = ptbl->score - 1;
  583. X    }
  584. X      return (true);
  585. X    }
  586. X  return (false);
  587. }
  588. X
  589. int
  590. PutInTTable (short int side,
  591. X         short int score,
  592. X         short int depth,
  593. X         short int alpha,
  594. X         short int beta,
  595. X         short unsigned int mv)
  596. X
  597. /*
  598. X  Store the current board position in the transposition table.
  599. */
  600. X
  601. {
  602. X  register struct hashentry *ptbl;
  603. X  register unsigned short i;
  604. X
  605. X  ptbl = &ttable[side][hashkey & (ttblsz - 1)];
  606. X
  607. X  /* rehash max rehash times */
  608. X  for (i = 1; depth < ptbl->depth && ptbl->hashbd != hashbd && i <= rehash; i++)
  609. X    ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)];
  610. X  if (depth >= ptbl->depth || ptbl->hashbd != hashbd)
  611. X    {
  612. X      HashAdd++;
  613. X      ptbl->hashbd = hashbd;
  614. X      ptbl->depth = (unsigned char) depth;
  615. X      ptbl->score = score;
  616. X      ptbl->mv = mv;
  617. X      if (score < alpha)
  618. X    ptbl->flags = upperbound;
  619. X      else if (score > beta)
  620. X    ptbl->flags = lowerbound;
  621. X      else
  622. X    ptbl->flags = truescore;
  623. #ifdef HASHTEST
  624. X      for (i = 0; i < 32; i++)
  625. X    {
  626. X      ptbl->bd[i] = CB (i);
  627. X    }
  628. #endif /* HASHTEST */
  629. X      return true;
  630. X    }
  631. X  return false;
  632. }
  633. X
  634. void
  635. ZeroTTable (void)
  636. {
  637. X  register int side, i;
  638. X
  639. X  if (flag.hash)
  640. X    for (side = white; side <= black; side++)
  641. X      for (i = 0; i < ttblsz; i++)
  642. X    ttable[side][i].depth = 0;
  643. }
  644. X
  645. #ifdef HASHFILE
  646. int
  647. ProbeFTable (short int side,
  648. X         short int depth,
  649. X         short int *alpha,
  650. X         short int *beta,
  651. X         short int *score)
  652. X
  653. /*
  654. X  Look for the current board position in the persistent transposition table.
  655. */
  656. X
  657. {
  658. X  register unsigned short i, j;
  659. X  register unsigned long hashix;
  660. X  short s;
  661. X  struct fileentry new, t;
  662. X
  663. X  hashix = ((side == white) ? (hashkey & 0xFFFFFFFE) : (hashkey | 1)) & filesz;
  664. X
  665. X  for (i = 0; i < 32; i++)
  666. X    new.bd[i] = CB (i);
  667. X  new.flags = 0;
  668. X  if (Mvboard[kingP[side]] == 0)
  669. X    {
  670. X      if (Mvboard[qrook[side]] == 0)
  671. X    new.flags |= queencastle;
  672. X      if (Mvboard[krook[side]] == 0)
  673. X    new.flags |= kingcastle;
  674. X    }
  675. X
  676. X  for (i = 0; i < frehash; i++)
  677. X    {
  678. X      fseek (hashfile,
  679. X         sizeof (struct fileentry) * ((hashix + 2 * i) & (filesz)),
  680. X         SEEK_SET);
  681. X      fread (&t, sizeof (struct fileentry), 1, hashfile);
  682. X      for (j = 0; j < 32; j++)
  683. X    if (t.bd[j] != new.bd[j])
  684. X      break;
  685. X      if (((short) t.depth >= depth) && (j >= 32)
  686. X      && (new.flags == (t.flags & (kingcastle | queencastle))))
  687. X    {
  688. X      FHashCnt++;
  689. X      PV = (t.f << 8) | t.t;
  690. X      s = (t.sh << 8) | t.sl;
  691. X      if (t.flags & truescore)
  692. X        {
  693. X          *score = s;
  694. X          *beta = -20000;
  695. X        }
  696. X      else if (t.flags & lowerbound)
  697. X        {
  698. X          if (s > *alpha)
  699. X        *alpha = s - 1;
  700. X        }
  701. X      return (true);
  702. X    }
  703. X    }
  704. X  return (false);
  705. }
  706. X
  707. void
  708. PutInFTable (short int side,
  709. X         short int score,
  710. X         short int depth,
  711. X         short int alpha,
  712. X         short int beta,
  713. X         short unsigned int f,
  714. X         short unsigned int t)
  715. X
  716. /*
  717. X  Store the current board position in the persistent transposition table.
  718. */
  719. X
  720. {
  721. X  register unsigned short i;
  722. X  register unsigned long hashix;
  723. X  struct fileentry new, tmp;
  724. X
  725. X  FHashAdd++;
  726. X  hashix = ((side == white) ? (hashkey & 0xFFFFFFFE) : (hashkey | 1)) & filesz;
  727. X  for (i = 0; i < 32; i++)
  728. X    new.bd[i] = CB (i);
  729. X  new.f = (unsigned char) f;
  730. X  new.t = (unsigned char) t;
  731. X  if (score < alpha)
  732. X    new.flags = upperbound;
  733. X  else
  734. X    new.flags = (score > beta) ? lowerbound : truescore;
  735. X  if (Mvboard[kingP[side]] == 0)
  736. X    {
  737. X      if (Mvboard[qrook[side]] == 0)
  738. X    new.flags |= queencastle;
  739. X      if (Mvboard[krook[side]] == 0)
  740. X    new.flags |= kingcastle;
  741. X    }
  742. X  new.depth = (unsigned char) depth;
  743. X  new.sh = (unsigned char) (score >> 8);
  744. X  new.sl = (unsigned char) (score & 0xFF);
  745. X
  746. X  for (i = 0; i < frehash; i++)
  747. X    {
  748. X      fseek (hashfile,
  749. X         sizeof (struct fileentry) * ((hashix + 2 * i) & (filesz)),
  750. X         SEEK_SET);
  751. X      fread (&tmp, sizeof (struct fileentry), 1, hashfile);
  752. X      if ((short) tmp.depth <= depth)
  753. X    {
  754. X      fseek (hashfile,
  755. X         sizeof (struct fileentry) * ((hashix + 2 * i) & (filesz)),
  756. X         SEEK_SET);
  757. X      fwrite (&new, sizeof (struct fileentry), 1, hashfile);
  758. X      break;
  759. X    }
  760. X    }
  761. }
  762. X
  763. #endif /* HASHFILE */
  764. #endif /* ttblsz */
  765. X
  766. void
  767. ZeroRPT (void)
  768. {
  769. X  register int side, i;
  770. X
  771. X  for (side = white; side <= black; side++)
  772. X    for (i = 0; i < 256; i++)
  773. X      rpthash[side][i] = 0;
  774. }
  775. X
  776. #define Link(from,to,flag,s) \
  777. {\
  778. X   node->f = from; node->t = to;\
  779. X     node->reply = 0;\
  780. X       node->flags = flag;\
  781. X     node->score = s;\
  782. X       ++node;\
  783. X         ++TrPnt[ply+1];\
  784. X         }
  785. X
  786. static inline void
  787. LinkMove (short int ply,
  788. X      short int f,
  789. X      short int t,
  790. X      short int flag,
  791. X      short int xside)
  792. X
  793. /*
  794. X  Add a move to the tree.  Assign a bonus to order the moves
  795. X  as follows:
  796. X  1. Principle variation
  797. X  2. Capture of last moved piece
  798. X  3. Other captures (major pieces first)
  799. X  4. Killer moves
  800. X  5. "history" killers
  801. */
  802. X
  803. {
  804. X  register short s, z;
  805. X  register unsigned short mv;
  806. X  register struct leaf *node;
  807. X  extern char mvstr[4][6];
  808. X
  809. X  node = &Tree[TrPnt[ply + 1]];
  810. X  mv = (f << 8) | t;
  811. X  s = 0;
  812. X  if (mv == Swag0)
  813. X    s = 2000;
  814. X  else if (mv == Swag1)
  815. X    s = 60;
  816. X  else if (mv == Swag2)
  817. X    s = 50;
  818. X  else if (mv == Swag3)
  819. X    s = 40;
  820. X  else if (mv == Swag4)
  821. X    s = 30;
  822. X  z = (f << 6) | t;
  823. X  if (xside == white)
  824. X    z |= 0x1000;
  825. X  s += history[z];
  826. X  if (color[t] != neutral)
  827. X    {
  828. X      if (t == TOsquare)
  829. X    s += 500;
  830. X      s += value[board[t]] - board[f];
  831. X    }
  832. X  if (board[f] == pawn)
  833. X    if (row (t) == 0 || row (t) == 7)
  834. X      {
  835. X    flag |= promote;
  836. X    s += 800;
  837. X    Link (f, t, flag | queen, s - 20000);
  838. X    s -= 200;
  839. X    Link (f, t, flag | knight, s - 20000);
  840. X    s -= 50;
  841. X    Link (f, t, flag | rook, s - 20000);
  842. X    flag |= bishop;
  843. X    s -= 50;
  844. X      }
  845. X    else if (row (t) == 1 || row (t) == 6)
  846. X      {
  847. X    flag |= pwnthrt;
  848. X    s += 600;
  849. X      }
  850. X  Link (f, t, flag, s - 20000);
  851. }
  852. X
  853. X
  854. static inline void
  855. GenMoves (short int ply, short int sq, short int side, short int xside)
  856. X
  857. /*
  858. X  Generate moves for a piece. The moves are taken from the precalulated
  859. X  array nextpos/nextdir. If the board is free, next move is choosen from
  860. X  nextpos else from nextdir.
  861. */
  862. X
  863. {
  864. X  register short u, piece;
  865. X  register unsigned char *ppos, *pdir;
  866. X
  867. X  piece = board[sq];
  868. X  ppos = nextpos[ptype[side][piece]][sq];
  869. X  pdir = nextdir[ptype[side][piece]][sq];
  870. X  if (piece == pawn)
  871. X    {
  872. X      u = ppos[sq];        /* follow no captures thread */
  873. X      if (color[u] == neutral)
  874. X    {
  875. X      LinkMove (ply, sq, u, 0, xside);
  876. X      u = ppos[u];
  877. X      if (color[u] == neutral)
  878. X        LinkMove (ply, sq, u, 0, xside);
  879. X    }
  880. X      u = pdir[sq];        /* follow captures thread */
  881. X      if (color[u] == xside)
  882. X    LinkMove (ply, sq, u, capture, xside);
  883. X      else if (u == epsquare)
  884. X    LinkMove (ply, sq, u, capture | epmask, xside);
  885. X      u = pdir[u];
  886. X      if (color[u] == xside)
  887. X    LinkMove (ply, sq, u, capture, xside);
  888. X      else if (u == epsquare)
  889. X    LinkMove (ply, sq, u, capture | epmask, xside);
  890. X    }
  891. X  else
  892. X    {
  893. X      u = ppos[sq];
  894. X      do
  895. X    {
  896. X      if (color[u] == neutral)
  897. X        {
  898. X          LinkMove (ply, sq, u, 0, xside);
  899. X          u = ppos[u];
  900. X        }
  901. X      else
  902. X        {
  903. X          if (color[u] == xside)
  904. X        LinkMove (ply, sq, u, capture, xside);
  905. X          u = pdir[u];
  906. X        }
  907. X      } while (u != sq);
  908. X    }
  909. }
  910. X
  911. void
  912. MoveList (short int side, short int ply)
  913. X
  914. /*
  915. X  Fill the array Tree[] with all available moves for side to play. Array
  916. X  TrPnt[ply] contains the index into Tree[] of the first move at a ply.
  917. */
  918. X
  919. {
  920. X  register short i, xside, f;
  921. X
  922. X  xside = otherside[side];
  923. X  TrPnt[ply + 1] = TrPnt[ply];
  924. X  Swag0 = (PV) ? killr0[ply] : PV;
  925. X  Swag1 = killr1[ply];
  926. X  Swag2 = killr2[ply];
  927. X  Swag3 = killr3[ply];
  928. X  Swag4 = (ply > 2) ? killr1[ply - 2] : 0;
  929. X  for (i = PieceCnt[side]; i >= 0; i--)
  930. X    GenMoves (ply, PieceList[side][i], side, xside);
  931. X  if (!castld[side])
  932. X    {
  933. X      f = PieceList[side][0];
  934. X      if (castle (side, f, f + 2, 0))
  935. X    {
  936. X      LinkMove (ply, f, f + 2, cstlmask, xside);
  937. X    }
  938. X      if (castle (side, f, f - 2, 0))
  939. X    {
  940. X      LinkMove (ply, f, f - 2, cstlmask, xside);
  941. X    }
  942. X    }
  943. }
  944. X
  945. void
  946. CaptureList (short int side, short int ply)
  947. X
  948. /*
  949. X  Fill the array Tree[] with all available cature and promote moves for
  950. X  side to play. Array TrPnt[ply] contains the index into Tree[]
  951. X  of the first move at a ply.
  952. */
  953. X
  954. {
  955. X  register short u, sq, xside;
  956. X  register struct leaf *node;
  957. X  register unsigned char *ppos, *pdir;
  958. X  short i, piece, *PL, r7;
  959. X
  960. X  xside = otherside[side];
  961. X  TrPnt[ply + 1] = TrPnt[ply];
  962. X  node = &Tree[TrPnt[ply]];
  963. X  r7 = rank7[side];
  964. X  PL = PieceList[side];
  965. X  for (i = 0; i <= PieceCnt[side]; i++)
  966. X    {
  967. X      sq = PL[i];
  968. X      piece = board[sq];
  969. X      if (sweep[piece])
  970. X    {
  971. X      ppos = nextpos[piece][sq];
  972. X      pdir = nextdir[piece][sq];
  973. X      u = ppos[sq];
  974. X      do
  975. X        {
  976. X          if (color[u] == neutral)
  977. X        u = ppos[u];
  978. X          else
  979. X        {
  980. X          if (color[u] == xside)
  981. X            Link (sq, u, capture, value[board[u]] + svalue[board[u]] - piece);
  982. X          u = pdir[u];
  983. X        }
  984. X      } while (u != sq);
  985. X    }
  986. X      else
  987. X    {
  988. X      pdir = nextdir[ptype[side][piece]][sq];
  989. X      if (piece == pawn && row (sq) == r7)
  990. X        {
  991. X          u = pdir[sq];
  992. X          if (color[u] == xside)
  993. X        Link (sq, u, capture | promote | queen, valueQ);
  994. X          u = pdir[u];
  995. X          if (color[u] == xside)
  996. X        Link (sq, u, capture | promote | queen, valueQ);
  997. X          ppos = nextpos[ptype[side][piece]][sq];
  998. X          u = ppos[sq];    /* also generate non capture promote */
  999. X          if (color[u] == neutral)
  1000. X        Link (sq, u, promote | queen, valueQ);
  1001. X        }
  1002. X      else
  1003. X        {
  1004. X          u = pdir[sq];
  1005. X          do
  1006. X        {
  1007. X          if (color[u] == xside)
  1008. X            Link (sq, u, capture, value[board[u]] + svalue[board[u]] - piece);
  1009. X          u = pdir[u];
  1010. X          } while (u != sq);
  1011. X        }
  1012. X    }
  1013. X    }
  1014. }
  1015. X
  1016. X
  1017. int
  1018. castle (short int side, short int kf, short int kt, short int iop)
  1019. X
  1020. /* Make or Unmake a castling move. */
  1021. X
  1022. {
  1023. X  register short rf, rt, t0, xside;
  1024. X
  1025. X  xside = otherside[side];
  1026. X  if (kt > kf)
  1027. X    {
  1028. X      rf = kf + 3;
  1029. X      rt = kt - 1;
  1030. X    }
  1031. X  else
  1032. X    {
  1033. X      rf = kf - 4;
  1034. X      rt = kt + 1;
  1035. X    }
  1036. X  if (iop == 0)
  1037. X    {
  1038. X      if (kf != kingP[side] ||
  1039. X      board[kf] != king ||
  1040. X      board[rf] != rook ||
  1041. X      Mvboard[kf] != 0 ||
  1042. X      Mvboard[rf] != 0 ||
  1043. X      color[kt] != neutral ||
  1044. X      color[rt] != neutral ||
  1045. X      color[kt - 1] != neutral ||
  1046. X      SqAtakd (kf, xside) ||
  1047. X      SqAtakd (kt, xside) ||
  1048. X      SqAtakd (rt, xside))
  1049. X    return (false);
  1050. X    }
  1051. X  else
  1052. X    {
  1053. X      if (iop == 1)
  1054. X    {
  1055. X      castld[side] = true;
  1056. X      Mvboard[kf]++;
  1057. X      Mvboard[rf]++;
  1058. X    }
  1059. X      else
  1060. X    {
  1061. X      castld[side] = false;
  1062. X      Mvboard[kf]--;
  1063. X      Mvboard[rf]--;
  1064. X      t0 = kt;
  1065. X      kt = kf;
  1066. X      kf = t0;
  1067. X      t0 = rt;
  1068. X      rt = rf;
  1069. X      rf = t0;
  1070. X    }
  1071. X      board[kt] = king;
  1072. X      color[rt] = color[kt] = side;
  1073. X      Pindex[kt] = 0;
  1074. X      board[kf] = no_piece;
  1075. X      color[rf] = color[kf] = neutral;
  1076. X      board[rt] = rook;
  1077. X      Pindex[rt] = Pindex[rf];
  1078. X      board[rf] = no_piece;
  1079. X      PieceList[side][Pindex[kt]] = kt;
  1080. X      PieceList[side][Pindex[rt]] = rt;
  1081. #if ttblsz
  1082. X      UpdateHashbd (side, king, kf, kt);
  1083. X      UpdateHashbd (side, rook, rf, rt);
  1084. #endif /* ttblsz */
  1085. X    }
  1086. X  return (true);
  1087. }
  1088. X
  1089. X
  1090. void
  1091. EnPassant (short int xside, short int f, short int t, short int iop)
  1092. X
  1093. /*
  1094. X  Make or unmake an en passant move.
  1095. */
  1096. X
  1097. {
  1098. X  register short l;
  1099. X
  1100. X  l = (t > f) ? t - 8 : t + 8;
  1101. X  if (iop == 1)
  1102. X    {
  1103. X      board[l] = no_piece;
  1104. X      color[l] = neutral;
  1105. X    }
  1106. X  else
  1107. X    {
  1108. X      board[l] = pawn;
  1109. X      color[l] = xside;
  1110. X    }
  1111. X  InitializeStats ();
  1112. }
  1113. X
  1114. X
  1115. static inline void
  1116. UpdatePieceList (short int side, short int sq, short int iop)
  1117. X
  1118. /*
  1119. X  Update the PieceList and Pindex arrays when a piece is captured or when a
  1120. X  capture is unmade.
  1121. */
  1122. X
  1123. {
  1124. X  register short i;
  1125. X  if (iop == 1)
  1126. X    {
  1127. X      PieceCnt[side]--;
  1128. X      for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1129. X    {
  1130. X      PieceList[side][i] = PieceList[side][i + 1];
  1131. X      Pindex[PieceList[side][i]] = i;
  1132. X    }
  1133. X    }
  1134. X  else
  1135. X    {
  1136. X      PieceCnt[side]++;
  1137. X      PieceList[side][PieceCnt[side]] = sq;
  1138. X      Pindex[sq] = PieceCnt[side];
  1139. X    }
  1140. }
  1141. X
  1142. void
  1143. MakeMove (short int side,
  1144. X      struct leaf * node,
  1145. X      short int *tempb,
  1146. X      short int *tempc,
  1147. X      short int *tempsf,
  1148. X      short int *tempst,
  1149. X      short int *INCscore)
  1150. X
  1151. /*
  1152. X  Update Arrays board[], color[], and Pindex[] to reflect the new board
  1153. X  position obtained after making the move pointed to by node. Also update
  1154. X  miscellaneous stuff that changes when a move is made.
  1155. */
  1156. X
  1157. {
  1158. X  register short f, t, xside, ct, cf;
  1159. X
  1160. X  xside = otherside[side];
  1161. X  GameCnt++;
  1162. X  f = node->f;
  1163. X  t = node->t;
  1164. X  epsquare = -1;
  1165. X  FROMsquare = f;
  1166. X  TOsquare = t;
  1167. X  *INCscore = 0;
  1168. X  GameList[GameCnt].gmove = (f << 8) | t;
  1169. X  GameList[GameCnt].flags = node->flags;
  1170. X  if (node->flags & cstlmask)
  1171. X    {
  1172. X      GameList[GameCnt].piece = no_piece;
  1173. X      GameList[GameCnt].color = side;
  1174. X      (void) castle (side, f, t, 1);
  1175. X    }
  1176. X  else
  1177. X    {
  1178. X      if (!(node->flags & capture) && (board[f] != pawn))
  1179. X    rpthash[side][hashkey & 0xFF]++;
  1180. X      *tempc = color[t];
  1181. X      *tempb = board[t];
  1182. X      *tempsf = svalue[f];
  1183. X      *tempst = svalue[t];
  1184. X      GameList[GameCnt].piece = *tempb;
  1185. X      GameList[GameCnt].color = *tempc;
  1186. X      if (*tempc != neutral)
  1187. X    {
  1188. X      UpdatePieceList (*tempc, t, 1);
  1189. X      if (*tempb == pawn)
  1190. X        --PawnCnt[*tempc][column (t)];
  1191. X      if (board[f] == pawn)
  1192. X        {
  1193. X          --PawnCnt[side][column (f)];
  1194. X          ++PawnCnt[side][column (t)];
  1195. X          cf = column (f);
  1196. X          ct = column (t);
  1197. X          if (PawnCnt[side][ct] > 1 + PawnCnt[side][cf])
  1198. X        *INCscore -= 15;
  1199. X          else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1200. X        *INCscore += 15;
  1201. X          else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1202. X        *INCscore -= 15;
  1203. X        }
  1204. X      mtl[xside] -= value[*tempb];
  1205. X      if (*tempb == pawn)
  1206. X        pmtl[xside] -= valueP;
  1207. #if ttblsz
  1208. X      UpdateHashbd (xside, *tempb, -1, t);
  1209. #endif /* ttblsz */
  1210. X      *INCscore += *tempst;
  1211. X      Mvboard[t]++;
  1212. X    }
  1213. X      color[t] = color[f];
  1214. X      board[t] = board[f];
  1215. X      svalue[t] = svalue[f];
  1216. X      Pindex[t] = Pindex[f];
  1217. X      PieceList[side][Pindex[t]] = t;
  1218. X      color[f] = neutral;
  1219. X      board[f] = no_piece;
  1220. X      if (board[t] == pawn)
  1221. X    if (t - f == 16)
  1222. X      epsquare = f + 8;
  1223. X    else if (f - t == 16)
  1224. X      epsquare = f - 8;
  1225. X      if (node->flags & promote)
  1226. X    {
  1227. X      board[t] = node->flags & pmask;
  1228. X      if (board[t] == queen)
  1229. X        HasQueen[side]++;
  1230. X      else if (board[t] == rook)
  1231. X        HasRook[side]++;
  1232. X      else if (board[t] == bishop)
  1233. X        HasBishop[side]++;
  1234. X      else if (board[t] == knight)
  1235. X        HasKnight[side]++;
  1236. X      --PawnCnt[side][column (t)];
  1237. X      mtl[side] += value[board[t]] - valueP;
  1238. X      pmtl[side] -= valueP;
  1239. #if ttblsz
  1240. X      UpdateHashbd (side, pawn, f, -1);
  1241. X      UpdateHashbd (side, board[t], f, -1);
  1242. #endif /* ttblsz */
  1243. X      *INCscore -= *tempsf;
  1244. X    }
  1245. X      if (node->flags & epmask)
  1246. X    EnPassant (xside, f, t, 1);
  1247. X      else
  1248. #if ttblsz
  1249. X    UpdateHashbd (side, board[t], f, t);
  1250. #else
  1251. X     /* NOOP */ ;
  1252. #endif /* ttblsz */
  1253. X      Mvboard[f]++;
  1254. X    }
  1255. }
  1256. X
  1257. void
  1258. UnmakeMove (short int side,
  1259. X        struct leaf * node,
  1260. X        short int *tempb,
  1261. X        short int *tempc,
  1262. X        short int *tempsf,
  1263. X        short int *tempst)
  1264. X
  1265. /*
  1266. X  Take back a move.
  1267. */
  1268. X
  1269. {
  1270. X  register short f, t, xside;
  1271. X
  1272. X  xside = otherside[side];
  1273. X  f = node->f;
  1274. X  t = node->t;
  1275. X  epsquare = -1;
  1276. X  GameCnt--;
  1277. X  if (node->flags & cstlmask)
  1278. X    (void) castle (side, f, t, 2);
  1279. X  else
  1280. X    {
  1281. X      color[f] = color[t];
  1282. X      board[f] = board[t];
  1283. X      svalue[f] = *tempsf;
  1284. X      Pindex[f] = Pindex[t];
  1285. X      PieceList[side][Pindex[f]] = f;
  1286. X      color[t] = *tempc;
  1287. X      board[t] = *tempb;
  1288. X      svalue[t] = *tempst;
  1289. X      if (node->flags & promote)
  1290. X    {
  1291. X      board[f] = pawn;
  1292. X      ++PawnCnt[side][column (t)];
  1293. X      mtl[side] += valueP - value[node->flags & pmask];
  1294. X      pmtl[side] += valueP;
  1295. #if ttblsz
  1296. X      UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  1297. X      UpdateHashbd (side, pawn, -1, t);
  1298. #endif /* ttblsz */
  1299. X    }
  1300. X      if (*tempc != neutral)
  1301. X    {
  1302. X      UpdatePieceList (*tempc, t, 2);
  1303. X      if (*tempb == pawn)
  1304. X        ++PawnCnt[*tempc][column (t)];
  1305. X      if (board[f] == pawn)
  1306. X        {
  1307. X          --PawnCnt[side][column (t)];
  1308. X          ++PawnCnt[side][column (f)];
  1309. X        }
  1310. X      mtl[xside] += value[*tempb];
  1311. X      if (*tempb == pawn)
  1312. X        pmtl[xside] += valueP;
  1313. #if ttblsz
  1314. X      UpdateHashbd (xside, *tempb, -1, t);
  1315. #endif /* ttblsz */
  1316. X      Mvboard[t]--;
  1317. X    }
  1318. X      if (node->flags & epmask)
  1319. X    EnPassant (xside, f, t, 2);
  1320. X      else
  1321. #if ttblsz
  1322. X    UpdateHashbd (side, board[f], f, t);
  1323. #else
  1324. X     /* NOOP */ ;
  1325. #endif /* ttblsz */
  1326. X      Mvboard[f]--;
  1327. X      if (!(node->flags & capture) && (board[f] != pawn))
  1328. X    rpthash[side][hashkey & 0xFF]--;
  1329. X    }
  1330. }
  1331. X
  1332. X
  1333. void
  1334. InitializeStats (void)
  1335. X
  1336. /*
  1337. X  Scan thru the board seeing what's on each square. If a piece is found,
  1338. X  update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1339. X  determine the material for each side and set the hashkey and hashbd
  1340. X  variables to represent the current board position. Array
  1341. X  PieceList[side][indx] contains the location of all the pieces of either
  1342. X  side. Array Pindex[sq] contains the indx into PieceList for a given
  1343. X  square.
  1344. */
  1345. X
  1346. {
  1347. X  register short i, sq;
  1348. X  epsquare = -1;
  1349. X  for (i = 0; i < 8; i++)
  1350. X    PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1351. X  mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1352. X  PieceCnt[white] = PieceCnt[black] = 0;
  1353. #if ttblsz
  1354. X  hashbd = hashkey = 0;
  1355. #endif /* ttblsz */
  1356. X  for (sq = 0; sq < 64; sq++)
  1357. X    if (color[sq] != neutral)
  1358. X      {
  1359. X    mtl[color[sq]] += value[board[sq]];
  1360. X    if (board[sq] == pawn)
  1361. X      {
  1362. X        pmtl[color[sq]] += valueP;
  1363. X        ++PawnCnt[color[sq]][column (sq)];
  1364. X      }
  1365. X    Pindex[sq] = (board[sq] == king) ? 0 : ++PieceCnt[color[sq]];
  1366. X    PieceList[color[sq]][Pindex[sq]] = sq;
  1367. #if ttblsz
  1368. X    hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  1369. X    hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  1370. #endif /* ttblsz */
  1371. X      }
  1372. }
  1373. X
  1374. X
  1375. int
  1376. SqAtakd (short int sq, short int side)
  1377. X
  1378. /*
  1379. X  See if any piece with color 'side' ataks sq.  First check pawns then Queen,
  1380. X  Bishop, Rook and King and last Knight.
  1381. */
  1382. X
  1383. {
  1384. X  register short u;
  1385. X  register unsigned char *ppos, *pdir;
  1386. X  short xside;
  1387. X
  1388. X  xside = otherside[side];
  1389. X  pdir = nextdir[ptype[xside][pawn]][sq];
  1390. X  u = pdir[sq];            /* follow captures thread */
  1391. X  if (u != sq)
  1392. X    {
  1393. X      if (board[u] == pawn && color[u] == side)
  1394. X    return (true);
  1395. X      u = pdir[u];
  1396. X      if (u != sq && board[u] == pawn && color[u] == side)
  1397. X    return (true);
  1398. X    }
  1399. X  /* king capture */
  1400. X  if (distance (sq, PieceList[side][0]) == 1)
  1401. X    return (true);
  1402. X  /* try a queen bishop capture */
  1403. X  ppos = nextpos[bishop][sq];
  1404. X  pdir = nextdir[bishop][sq];
  1405. X  u = ppos[sq];
  1406. X  do
  1407. X    {
  1408. X      if (color[u] == neutral)
  1409. X    u = ppos[u];
  1410. X      else
  1411. X    {
  1412. X      if (color[u] == side && (board[u] == queen || board[u] == bishop))
  1413. X        return (true);
  1414. X      u = pdir[u];
  1415. X    }
  1416. X  } while (u != sq);
  1417. X  /* try a queen rook capture */
  1418. X  ppos = nextpos[rook][sq];
  1419. X  pdir = nextdir[rook][sq];
  1420. X  u = ppos[sq];
  1421. X  do
  1422. X    {
  1423. X      if (color[u] == neutral)
  1424. X    u = ppos[u];
  1425. X      else
  1426. X    {
  1427. X      if (color[u] == side && (board[u] == queen || board[u] == rook))
  1428. X        return (true);
  1429. X      u = pdir[u];
  1430. X    }
  1431. X  } while (u != sq);
  1432. X  /* try a knight capture */
  1433. X  pdir = nextdir[knight][sq];
  1434. X  u = pdir[sq];
  1435. X  do
  1436. X    {
  1437. X      if (color[u] == side && board[u] == knight)
  1438. X    return (true);
  1439. X      u = pdir[u];
  1440. X  } while (u != sq);
  1441. X  return (false);
  1442. }
  1443. X
  1444. static inline void
  1445. ataks (short int side, short int *a)
  1446. X
  1447. /*
  1448. X  Fill array atak[][] with info about ataks to a square.  Bits 8-15 are set
  1449. X  if the piece (king..pawn) ataks the square.  Bits 0-7 contain a count of
  1450. X  total ataks to the square.
  1451. */
  1452. X
  1453. {
  1454. X  register short u, c, sq;
  1455. X  register unsigned char *ppos, *pdir;
  1456. X  short i, piece, *PL;
  1457. X
  1458. #ifdef NOMEMSET
  1459. X  for (u = 64; u; a[--u] = 0) ;
  1460. #else
  1461. X  memset ((char *) a, 0, 64 * sizeof (a[0]));
  1462. #endif /* NOMEMSET */
  1463. X  PL = PieceList[side];
  1464. X  for (i = PieceCnt[side]; i >= 0; i--)
  1465. X    {
  1466. X      sq = PL[i];
  1467. X      piece = board[sq];
  1468. X      c = control[piece];
  1469. X      if (sweep[piece])
  1470. X    {
  1471. X      ppos = nextpos[piece][sq];
  1472. X      pdir = nextdir[piece][sq];
  1473. X      u = ppos[sq];
  1474. X      do
  1475. X        {
  1476. X          a[u] = ++a[u] | c;
  1477. X          u = (color[u] == neutral) ? ppos[u] : pdir[u];
  1478. X      } while (u != sq);
  1479. X    }
  1480. X      else
  1481. X    {
  1482. X      pdir = nextdir[ptype[side][piece]][sq];
  1483. X      u = pdir[sq];        /* follow captures thread for pawns */
  1484. X      do
  1485. X        {
  1486. X          a[u] = ++a[u] | c;
  1487. X          u = pdir[u];
  1488. X      } while (u != sq);
  1489. X    }
  1490. X    }
  1491. }
  1492. X
  1493. X
  1494. /* ............    POSITIONAL EVALUATION ROUTINES    ............ */
  1495. X
  1496. int
  1497. evaluate (short int side,
  1498. X      short int ply,
  1499. X      short int alpha,
  1500. X      short int beta,
  1501. X      short int INCscore,
  1502. X      short int *slk,
  1503. X      short int *InChk)
  1504. X
  1505. /*
  1506. X  Compute an estimate of the score by adding the positional score from the
  1507. X  previous ply to the material difference. If this score falls inside a
  1508. X  window which is 180 points wider than the alpha-beta window (or within a
  1509. X  50 point window during quiescence search) call ScorePosition() to
  1510. X  determine a score, otherwise return the estimated score. If one side has
  1511. X  only a king and the other either has no pawns or no pieces then the
  1512. X  function ScoreLoneKing() is called.
  1513. */
  1514. X
  1515. {
  1516. X  register short evflag, xside;
  1517. X  short s;
  1518. X
  1519. X  xside = otherside[side];
  1520. X  s = -Pscore[ply - 1] + mtl[side] - mtl[xside] - INCscore;
  1521. X  hung[white] = hung[black] = 0;
  1522. X  *slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
  1523. X      (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0)));
  1524. X
  1525. X  if (*slk)
  1526. X    evflag = false;
  1527. X  else
  1528. X    evflag = (ply == 1 || ply < Sdepth ||
  1529. X          ((ply == Sdepth + 1 || ply == Sdepth + 2) &&
  1530. X           (s > alpha - xwndw && s < beta + xwndw)) ||
  1531. X          (ply > Sdepth + 2 && s >= alpha - 25 && s <= beta + 25));
  1532. X
  1533. X  if (evflag)
  1534. X    {
  1535. X      EvalNodes++;
  1536. X      ataks (side, atak[side]);
  1537. X      if (Anyatak (side, PieceList[xside][0]))
  1538. X    return (10001 - ply);
  1539. X      ataks (xside, atak[xside]);
  1540. X      *InChk = Anyatak (xside, PieceList[side][0]);
  1541. X      ScorePosition (side, &s);
  1542. X    }
  1543. X  else
  1544. X    {
  1545. X      if (SqAtakd (PieceList[xside][0], side))
  1546. X    return (10001 - ply);
  1547. X      *InChk = SqAtakd (PieceList[side][0], xside);
  1548. X      if (*slk)
  1549. X    ScoreLoneKing (side, &s);
  1550. X    }
  1551. X
  1552. X  Pscore[ply] = s - mtl[side] + mtl[xside];
  1553. X  if (*InChk)
  1554. X    ChkFlag[ply - 1] = Pindex[TOsquare];
  1555. X  else
  1556. X    ChkFlag[ply - 1] = 0;
  1557. X  return (s);
  1558. }
  1559. X
  1560. X
  1561. static inline int
  1562. ScoreKPK (short int side,
  1563. X      short int winner,
  1564. X      short int loser,
  1565. X      short int king1,
  1566. X      short int king2,
  1567. X      short int sq)
  1568. X
  1569. /*
  1570. X  Score King and Pawns versus King endings.
  1571. */
  1572. X
  1573. {
  1574. X  register short s, r;
  1575. X
  1576. X  if (PieceCnt[winner] == 1)
  1577. X    s = 50;
  1578. X  else
  1579. X    s = 120;
  1580. X  if (winner == white)
  1581. X    {
  1582. X      if (side == loser)
  1583. X    r = row (sq) - 1;
  1584. X      else
  1585. X    r = row (sq);
  1586. X      if (row (king2) >= r && distance (sq, king2) < 8 - r)
  1587. X    s += 10 * row (sq);
  1588. X      else
  1589. X    s = 500 + 50 * row (sq);
  1590. X      if (row (sq) < 6)
  1591. X    sq += 16;
  1592. X      else if (row (sq) == 6)
  1593. X    sq += 8;
  1594. X    }
  1595. X  else
  1596. X    {
  1597. X      if (side == loser)
  1598. X    r = row (sq) + 1;
  1599. X      else
  1600. X    r = row (sq);
  1601. X      if (row (king2) <= r && distance (sq, king2) < r + 1)
  1602. X    s += 10 * (7 - row (sq));
  1603. X      else
  1604. X    s = 500 + 50 * (7 - row (sq));
  1605. X      if (row (sq) > 1)
  1606. X    sq -= 16;
  1607. X      else if (row (sq) == 1)
  1608. X    sq -= 8;
  1609. X    }
  1610. X  s += 8 * (taxicab (king2, sq) - taxicab (king1, sq));
  1611. X  return (s);
  1612. }
  1613. X
  1614. X
  1615. static inline int
  1616. ScoreKBNK (short int winner, short int king1, short int king2)
  1617. X
  1618. X
  1619. /*
  1620. X  Score King+Bishop+Knight versus King endings.
  1621. X  This doesn't work all that well but it's better than nothing.
  1622. */
  1623. X
  1624. {
  1625. X  register short s, sq, KBNKsq = 0;
  1626. X
  1627. X  for (sq = 0; sq < 64; sq++)
  1628. X    if (board[sq] == bishop)
  1629. X      if (row (sq) % 2 == column (sq) % 2)
  1630. X    KBNKsq = 0;
  1631. X      else
  1632. X    KBNKsq = 7;
  1633. X
  1634. X  s = emtl[winner] - 300;
  1635. X  if (KBNKsq == 0)
  1636. X    s += KBNK[king2];
  1637. X  else
  1638. X    s += KBNK[locn (row (king2), 7 - column (king2))];
  1639. X  s -= taxicab (king1, king2);
  1640. X  s -= distance (PieceList[winner][1], king2);
  1641. X  s -= distance (PieceList[winner][2], king2);
  1642. X  return (s);
  1643. }
  1644. X
  1645. X
  1646. void
  1647. ScoreLoneKing (short int side, short int *score)
  1648. X
  1649. /*
  1650. X  Static evaluation when loser has only a king and winner has no pawns or no
  1651. X  pieces.
  1652. */
  1653. X
  1654. {
  1655. X  register short winner, loser, king1, king2, s, i;
  1656. X
  1657. X  UpdateWeights ();
  1658. X  if (mtl[white] > mtl[black])
  1659. X    winner = white;
  1660. X  else
  1661. X    winner = black;
  1662. X  loser = otherside[winner];
  1663. X  king1 = PieceList[winner][0];
  1664. X  king2 = PieceList[loser][0];
  1665. X
  1666. X  s = 0;
  1667. X
  1668. X  if (pmtl[winner] > 0)
  1669. X    for (i = 1; i <= PieceCnt[winner]; i++)
  1670. X      s += ScoreKPK (side, winner, loser, king1, king2, PieceList[winner][i]);
  1671. X
  1672. X  else if (emtl[winner] == valueB + valueN)
  1673. X    s = ScoreKBNK (winner, king1, king2);
  1674. X
  1675. X  else if (emtl[winner] > valueB)
  1676. X    s = 500 + emtl[winner] - DyingKing[king2] - 2 * distance (king1, king2);
  1677. X
  1678. X  if (side == winner)
  1679. X    *score = s;
  1680. X  else
  1681. X    *score = -s;
  1682. }
  1683. X
  1684. X
  1685. static inline void
  1686. BRscan (short int sq, short int *s, short int *mob)
  1687. X
  1688. /*
  1689. X  Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
  1690. X  hung[] array if a pin is found.
  1691. */
  1692. {
  1693. X  register short u, piece, pin;
  1694. X  register unsigned char *ppos, *pdir;
  1695. X  short *Kf;
  1696. X
  1697. X  Kf = Kfield[c1];
  1698. X  *mob = 0;
  1699. X  piece = board[sq];
  1700. X  ppos = nextpos[piece][sq];
  1701. X  pdir = nextdir[piece][sq];
  1702. X  u = ppos[sq];
  1703. X  pin = -1;            /* start new direction */
  1704. X  do
  1705. X    {
  1706. X      *s += Kf[u];
  1707. X      if (color[u] == neutral)
  1708. X    {
  1709. X      (*mob)++;
  1710. X      if (ppos[u] == pdir[u])
  1711. X        pin = -1;        /* oops new direction */
  1712. X      u = ppos[u];
  1713. X    }
  1714. X      else if (pin < 0)
  1715. X    {
  1716. X      if (board[u] == pawn || board[u] == king)
  1717. X        u = pdir[u];
  1718. X      else
  1719. X        {
  1720. X          if (ppos[u] != pdir[u])
  1721. X        pin = u;    /* not on the edge and on to find a pin */
  1722. X          u = ppos[u];
  1723. X        }
  1724. X    }
  1725. X      else
  1726. X    {
  1727. X      if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
  1728. X        {
  1729. X          if (color[pin] == c2)
  1730. X        {
  1731. X          *s += PINVAL;
  1732. X          if (atk2[pin] == 0 ||
  1733. X              atk1[pin] > control[board[pin]] + 1)
  1734. X            ++hung[c2];
  1735. X        }
  1736. X          else
  1737. X        *s += XRAY;
  1738. X        }
  1739. X      pin = -1;        /* new direction */
  1740. X      u = pdir[u];
  1741. X    }
  1742. X  } while (u != sq);
  1743. }
  1744. X
  1745. X
  1746. static inline void
  1747. KingScan (short int sq, short int *s)
  1748. X
  1749. /*
  1750. X  Assign penalties if king can be threatened by checks, if squares
  1751. X  near the king are controlled by the enemy (especially the queen),
  1752. X  or if there are no pawns near the king.
  1753. X  The following must be true:
  1754. X  board[sq] == king
  1755. X  c1 == color[sq]
  1756. X  c2 == otherside[c1]
  1757. */
  1758. X
  1759. #define ScoreThreat \
  1760. X    if (color[u] != c2)\
  1761. X      if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
  1762. X      else *s -= 3
  1763. X
  1764. {
  1765. X  register short u;
  1766. X  register unsigned char *ppos, *pdir;
  1767. X  register short cnt, ok;
  1768. X
  1769. X  cnt = 0;
  1770. X  if (HasBishop[c2] || HasQueen[c2])
  1771. X    {
  1772. X      ppos = nextpos[bishop][sq];
  1773. X      pdir = nextdir[bishop][sq];
  1774. X      u = ppos[sq];
  1775. X      do
  1776. X    {
  1777. X      if (atk2[u] & ctlBQ)
  1778. X        ScoreThreat;
  1779. X      u = (color[u] == neutral) ? ppos[u] : pdir[u];
  1780. X      } while (u != sq);
  1781. X    }
  1782. X  if (HasRook[c2] || HasQueen[c2])
  1783. X    {
  1784. X      ppos = nextpos[rook][sq];
  1785. X      pdir = nextdir[rook][sq];
  1786. X      u = ppos[sq];
  1787. X      do
  1788. X    {
  1789. X      if (atk2[u] & ctlRQ)
  1790. X        ScoreThreat;
  1791. X      u = (color[u] == neutral) ? ppos[u] : pdir[u];
  1792. X      } while (u != sq);
  1793. X    }
  1794. X  if (HasKnight[c2])
  1795. X    {
  1796. X      pdir = nextdir[knight][sq];
  1797. X      u = pdir[sq];
  1798. X      do
  1799. X    {
  1800. X      if (atk2[u] & ctlNN)
  1801. X        ScoreThreat;
  1802. X      u = pdir[u];
  1803. X      } while (u != sq);
  1804. X    }
  1805. X  *s += (KSFTY * KTHRT[cnt]) / 16;
  1806. X
  1807. X  cnt = 0;
  1808. X  ok = false;
  1809. X  pdir = nextpos[king][sq];
  1810. X  u = pdir[sq];
  1811. X  do
  1812. X    {
  1813. X      if (board[u] == pawn)
  1814. X    ok = true;
  1815. X      if (atk2[u] > atk1[u])
  1816. X    {
  1817. X      ++cnt;
  1818. X      if (atk2[u] & ctlQ)
  1819. X        if (atk2[u] > ctlQ + 1 && atk1[u] < ctlQ)
  1820. X          *s -= 4 * KSFTY;
  1821. X    }
  1822. X      u = pdir[u];
  1823. X  } while (u != sq);
  1824. X  if (!ok)
  1825. X    *s -= KSFTY;
  1826. X  if (cnt > 1)
  1827. X    *s -= KSFTY;
  1828. }
  1829. X
  1830. X
  1831. static inline int
  1832. trapped (short int sq)
  1833. X
  1834. /*
  1835. X  See if the attacked piece has unattacked squares to move to.
  1836. X  The following must be true:
  1837. X  c1 == color[sq]
  1838. X  c2 == otherside[c1]
  1839. */
  1840. X
  1841. {
  1842. X  register short u, piece;
  1843. X  register unsigned char *ppos, *pdir;
  1844. X
  1845. X  piece = board[sq];
  1846. X  ppos = nextpos[ptype[c1][piece]][sq];
  1847. X  pdir = nextdir[ptype[c1][piece]][sq];
  1848. X  if (piece == pawn)
  1849. X    {
  1850. X      u = ppos[sq];        /* follow no captures thread */
  1851. X      if (color[u] == neutral)
  1852. X    {
  1853. X      if (atk1[u] >= atk2[u])
  1854. X        return (false);
  1855. X      if (atk2[u] < ctlP)
  1856. X        {
  1857. X          u = ppos[u];
  1858. X          if (color[u] == neutral && atk1[u] >= atk2[u])
  1859. X        return (false);
  1860. X        }
  1861. X    }
  1862. X      u = pdir[sq];        /* follow captures thread */
  1863. X      if (color[u] == c2)
  1864. X    return (false);
  1865. X      u = pdir[u];
  1866. X      if (color[u] == c2)
  1867. X    return (false);
  1868. X    }
  1869. X  else
  1870. X    {
  1871. X      u = ppos[sq];
  1872. X      do
  1873. X    {
  1874. X      if (color[u] != c1)
  1875. X        if (atk2[u] == 0 || board[u] >= piece)
  1876. X          return (false);
  1877. X      u = (color[u] == neutral) ? ppos[u] : pdir[u];
  1878. X      } while (u != sq);
  1879. X    }
  1880. X  return (true);
  1881. }
  1882. X
  1883. X
  1884. static inline int
  1885. PawnValue (short int sq, short int side)
  1886. X
  1887. /*
  1888. X  Calculate the positional value for a pawn on 'sq'.
  1889. */
  1890. X
  1891. {
  1892. X  register short j, fyle, rank;
  1893. X  register short s, a1, a2, in_square, r, e;
  1894. X
  1895. X  a1 = (atk1[sq] & 0x4FFF);
  1896. X  a2 = (atk2[sq] & 0x4FFF);
  1897. X  rank = row (sq);
  1898. X  fyle = column (sq);
  1899. X  s = 0;
  1900. X  if (c1 == white)
  1901. X    {
  1902. X      s = Mwpawn[sq];
  1903. X      if ((sq == 11 && color[19] != neutral)
  1904. X      || (sq == 12 && color[20] != neutral))
  1905. X    s += PEDRNK2B;
  1906. X      if ((fyle == 0 || PC1[fyle - 1] == 0)
  1907. X      && (fyle == 7 || PC1[fyle + 1] == 0))
  1908. X    s += ISOLANI[fyle];
  1909. X      else if (PC1[fyle] > 1)
  1910. X    s += PDOUBLED;
  1911. X      if (a1 < ctlP && atk1[sq + 8] < ctlP)
  1912. X    {
  1913. X      s += BACKWARD[a2 & 0xFF];
  1914. X      if (PC2[fyle] == 0)
  1915. X        s += PWEAKH;
  1916. X      if (color[sq + 8] != neutral)
  1917. X        s += PBLOK;
  1918. X    }
  1919. X      if (PC2[fyle] == 0)
  1920. X    {
  1921. X      if (side == black)
  1922. X        r = rank - 1;
  1923. X      else
  1924. X        r = rank;
  1925. X      in_square = (row (bking) >= r && distance (sq, bking) < 8 - r);
  1926. X      if (a2 == 0 || side == white)
  1927. X        e = 0;
  1928. X      else
  1929. X        e = 1;
  1930. X      for (j = sq + 8; j < 64; j += 8)
  1931. X        if (atk2[j] >= ctlP)
  1932. X          {
  1933. X        e = 2;
  1934. X        break;
  1935. X          }
  1936. X        else if (atk2[j] > 0 || color[j] != neutral)
  1937. X          e = 1;
  1938. X      if (e == 2)
  1939. X        s += (stage * PassedPawn3[rank]) / 10;
  1940. X      else if (in_square || e == 1)
  1941. X        s += (stage * PassedPawn2[rank]) / 10;
  1942. X      else if (emtl[black] > 0)
  1943. X        s += (stage * PassedPawn1[rank]) / 10;
  1944. X      else
  1945. X        s += PassedPawn0[rank];
  1946. X    }
  1947. X    }
  1948. X  else if (c1 == black)
  1949. X    {
  1950. X      s = Mbpawn[sq];
  1951. X      if ((sq == 51 && color[43] != neutral)
  1952. X      || (sq == 52 && color[44] != neutral))
  1953. X    s += PEDRNK2B;
  1954. X      if ((fyle == 0 || PC1[fyle - 1] == 0) &&
  1955. X      (fyle == 7 || PC1[fyle + 1] == 0))
  1956. X    s += ISOLANI[fyle];
  1957. X      else if (PC1[fyle] > 1)
  1958. X    s += PDOUBLED;
  1959. X      if (a1 < ctlP && atk1[sq - 8] < ctlP)
  1960. X    {
  1961. X      s += BACKWARD[a2 & 0xFF];
  1962. X      if (PC2[fyle] == 0)
  1963. X        s += PWEAKH;
  1964. X      if (color[sq - 8] != neutral)
  1965. X        s += PBLOK;
  1966. X    }
  1967. X      if (PC2[fyle] == 0)
  1968. X    {
  1969. X      if (side == white)
  1970. X        r = rank + 1;
  1971. X      else
  1972. X        r = rank;
  1973. X      in_square = (row (wking) <= r && distance (sq, wking) < r + 1);
  1974. X      if (a2 == 0 || side == black)
  1975. X        e = 0;
  1976. X      else
  1977. X        e = 1;
  1978. X      for (j = sq - 8; j >= 0; j -= 8)
  1979. X        if (atk2[j] >= ctlP)
  1980. X          {
  1981. X        e = 2;
  1982. X        break;
  1983. X          }
  1984. X        else if (atk2[j] > 0 || color[j] != neutral)
  1985. X          e = 1;
  1986. X      if (e == 2)
  1987. X        s += (stage * PassedPawn3[7 - rank]) / 10;
  1988. X      else if (in_square || e == 1)
  1989. X        s += (stage * PassedPawn2[7 - rank]) / 10;
  1990. X      else if (emtl[white] > 0)
  1991. X        s += (stage * PassedPawn1[7 - rank]) / 10;
  1992. X      else
  1993. X        s += PassedPawn0[7 - rank];
  1994. X    }
  1995. X    }
  1996. X  if (a2 > 0)
  1997. X    {
  1998. X      if (a1 == 0 || a2 > ctlP + 1)
  1999. X    {
  2000. X      s += HUNGP;
  2001. X      ++hung[c1];
  2002. X      if (trapped (sq))
  2003. X        ++hung[c1];
  2004. X    }
  2005. X      else if (a2 > a1)
  2006. X    s += ATAKD;
  2007. X    }
  2008. X  return (s);
  2009. }
  2010. X
  2011. X
  2012. static inline int
  2013. KnightValue (short int sq, short int side)
  2014. X
  2015. /*
  2016. X  Calculate the positional value for a knight on 'sq'.
  2017. */
  2018. X
  2019. {
  2020. X  register short s, a2, a1;
  2021. X
  2022. X  s = Mknight[c1][sq];
  2023. X  a2 = (atk2[sq] & 0x4FFF);
  2024. X  if (a2 > 0)
  2025. X    {
  2026. X      a1 = (atk1[sq] & 0x4FFF);
  2027. X      if (a1 == 0 || a2 > ctlBN + 1)
  2028. X    {
  2029. X      s += HUNGP;
  2030. X      ++hung[c1];
  2031. X      if (trapped (sq))
  2032. X        ++hung[c1];
  2033. X    }
  2034. X      else if (a2 >= ctlBN || a1 < ctlP)
  2035. X    s += ATAKD;
  2036. X    }
  2037. X  return (s);
  2038. }
  2039. X
  2040. X
  2041. static inline int
  2042. BishopValue (short int sq, short int side)
  2043. X
  2044. /*
  2045. X  Calculate the positional value for a bishop on 'sq'.
  2046. */
  2047. X
  2048. {
  2049. X  register short a2, a1;
  2050. X  short s, mob;
  2051. X
  2052. X  s = Mbishop[c1][sq];
  2053. X  BRscan (sq, &s, &mob);
  2054. X  s += BMBLTY[mob];
  2055. X  a2 = (atk2[sq] & 0x4FFF);
  2056. X  if (a2 > 0)
  2057. X    {
  2058. X      a1 = (atk1[sq] & 0x4FFF);
  2059. X      if (a1 == 0 || a2 > ctlBN + 1)
  2060. X    {
  2061. X      s += HUNGP;
  2062. X      ++hung[c1];
  2063. X      if (trapped (sq))
  2064. X        ++hung[c1];
  2065. X    }
  2066. X      else if (a2 >= ctlBN || a1 < ctlP)
  2067. X    s += ATAKD;
  2068. X    }
  2069. X  return (s);
  2070. }
  2071. X
  2072. X
  2073. static inline int
  2074. RookValue (short int sq, short int side)
  2075. X
  2076. /*
  2077. X  Calculate the positional value for a rook on 'sq'.
  2078. */
  2079. X
  2080. {
  2081. X  register short fyle, a2, a1;
  2082. X  short s, mob;
  2083. X
  2084. X  s = RookBonus;
  2085. X  BRscan (sq, &s, &mob);
  2086. X  s += RMBLTY[mob];
  2087. X  fyle = column (sq);
  2088. X  if (PC1[fyle] == 0)
  2089. X    s += RHOPN;
  2090. X  if (PC2[fyle] == 0)
  2091. X    s += RHOPNX;
  2092. X  if (pmtl[c2] > 100 && row (sq) == rank7[c1])
  2093. X    s += 10;
  2094. X  if (stage > 2)
  2095. X    s += 14 - taxicab (sq, EnemyKing);
  2096. X  a2 = (atk2[sq] & 0x4FFF);
  2097. X  if (a2 > 0)
  2098. X    {
  2099. X      a1 = (atk1[sq] & 0x4FFF);
  2100. X      if (a1 == 0 || a2 > ctlR + 1)
  2101. X    {
  2102. X      s += HUNGP;
  2103. X      ++hung[c1];
  2104. X
  2105. X      if (trapped (sq))
  2106. X        ++hung[c1];
  2107. X    }
  2108. X      else if (a2 >= ctlR || a1 < ctlP)
  2109. X    s += ATAKD;
  2110. X    }
  2111. X  return (s);
  2112. }
  2113. X
  2114. X
  2115. static inline int
  2116. QueenValue (short int sq, short int side)
  2117. X
  2118. /*
  2119. X  Calculate the positional value for a queen on 'sq'.
  2120. */
  2121. X
  2122. {
  2123. X  register short s, a2, a1;
  2124. X
  2125. X  s = (distance (sq, EnemyKing) < 3) ? 12 : 0;
  2126. X  if (stage > 2)
  2127. X    s += 14 - taxicab (sq, EnemyKing);
  2128. X  a2 = (atk2[sq] & 0x4FFF);
  2129. X  if (a2 > 0)
  2130. X    {
  2131. X      a1 = (atk1[sq] & 0x4FFF);
  2132. X      if (a1 == 0 || a2 > ctlQ + 1)
  2133. X    {
  2134. X      s += HUNGP;
  2135. X      ++hung[c1];
  2136. X      if (trapped (sq))
  2137. X        ++hung[c1];
  2138. X    }
  2139. X      else if (a2 >= ctlQ || a1 < ctlP)
  2140. X    s += ATAKD;
  2141. X    }
  2142. X  return (s);
  2143. }
  2144. X
  2145. X
  2146. static inline int
  2147. KingValue (short int sq, short int side)
  2148. X
  2149. /*
  2150. X  Calculate the positional value for a king on 'sq'.
  2151. */
  2152. X
  2153. {
  2154. X  register short fyle, a2, a1;
  2155. X  short s;
  2156. X
  2157. X  s = Mking[c1][sq];
  2158. X  if (KSFTY > 0)
  2159. X    if (Developed[c2] || stage > 0)
  2160. X      KingScan (sq, &s);
  2161. X  if (castld[c1])
  2162. X    s += KCASTLD;
  2163. X  else if (Mvboard[kingP[c1]])
  2164. X    s += KMOVD;
  2165. X
  2166. X  fyle = column (sq);
  2167. X  if (PC1[fyle] == 0)
  2168. X    s += KHOPN;
  2169. X  if (PC2[fyle] == 0)
  2170. X    s += KHOPNX;
  2171. X  switch (fyle)
  2172. X    {
  2173. X    case 5:
  2174. X      if (PC1[7] == 0)
  2175. X    s += KHOPN;
  2176. X      if (PC2[7] == 0)
  2177. X    s += KHOPNX;
  2178. X      /* Fall through */
  2179. X    case 4:
  2180. X    case 6:
  2181. X    case 0:
  2182. X      if (PC1[fyle + 1] == 0)
  2183. X    s += KHOPN;
  2184. X      if (PC2[fyle + 1] == 0)
  2185. X    s += KHOPNX;
  2186. X      break;
  2187. X    case 2:
  2188. X      if (PC1[0] == 0)
  2189. X    s += KHOPN;
  2190. X      if (PC2[0] == 0)
  2191. X    s += KHOPNX;
  2192. X      /* Fall through */
  2193. X    case 3:
  2194. X    case 1:
  2195. X    case 7:
  2196. X      if (PC1[fyle - 1] == 0)
  2197. X    s += KHOPN;
  2198. X      if (PC2[fyle - 1] == 0)
  2199. X    s += KHOPNX;
  2200. X      break;
  2201. X    default:
  2202. X      /* Impossible! */
  2203. X      break;
  2204. X    }
  2205. X
  2206. X  a2 = (atk2[sq] & 0x4FFF);
  2207. X  if (a2 > 0)
  2208. X    {
  2209. X      a1 = (atk1[sq] & 0x4FFF);
  2210. X      if (a1 == 0 || a2 > ctlK + 1)
  2211. X    {
  2212. X      s += HUNGP;
  2213. X      ++hung[c1];
  2214. X    }
  2215. X      else
  2216. X    s += ATAKD;
  2217. X    }
  2218. X  return (s);
  2219. }
  2220. X
  2221. X
  2222. void
  2223. ScorePosition (short int side, short int *score)
  2224. X
  2225. /*
  2226. X  Perform normal static evaluation of board position. A score is generated
  2227. X  for each piece and these are summed to get a score for each side.
  2228. */
  2229. X
  2230. {
  2231. X  register short sq, s, i, xside;
  2232. X  short pscore[2];
  2233. X
  2234. X  UpdateWeights ();
  2235. X  xside = otherside[side];
  2236. X  pscore[white] = pscore[black] = 0;
  2237. X
  2238. X  for (c1 = white; c1 <= black; c1++)
  2239. X    {
  2240. X      c2 = otherside[c1];
  2241. X      atk1 = atak[c1];
  2242. X      atk2 = atak[c2];
  2243. X      PC1 = PawnCnt[c1];
  2244. X      PC2 = PawnCnt[c2];
  2245. X      for (i = PieceCnt[c1]; i >= 0; i--)
  2246. X    {
  2247. X      sq = PieceList[c1][i];
  2248. X      switch (board[sq])
  2249. X        {
  2250. X        case pawn:
  2251. X          s = PawnValue (sq, side);
  2252. X          break;
  2253. SHAR_EOF
  2254. true || echo 'restore of gnuchess.c failed'
  2255. fi
  2256. echo 'End of  part 4'
  2257. echo 'File gnuchess.c is continued in part 5'
  2258. echo 5 > _shar_seq_.tmp
  2259. exit 0
  2260. exit 0 # Just in case...
  2261. -- 
  2262. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  2263. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  2264. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  2265. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  2266.  
  2267.  
  2268.