home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / wps / games / gnuchess / sources / search.c < prev    next >
Text File  |  1990-11-29  |  42KB  |  1,600 lines

  1. //
  2. //  Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  3. //  Copyright (c) 1988, 1989, 1990  John Stanback
  4. //
  5. //  Project:    OS/2 PM Port of GNU CHESS 3.1 (PmChess)
  6. //
  7. //  Version:    1990-11-17
  8. //
  9. //   Module:    Search Logic (Search.c)
  10. //
  11. //   Porter:    Ported to Windows 3.0 by Darly Baker
  12. //
  13. //   Porter:    Ported to OS/2 1.2+ by Kent Cedola
  14. //
  15. //   System:    OS2 1.2 using Microsoft C 6.0
  16. //
  17. //  Remarks:    This code converted to OS/2 almost as is.  Mostly minor changes
  18. //              to convert the small amount of Windows code to OS/2 PM.
  19. //
  20. //  License:
  21. //
  22. //    CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  23. //    WARRANTY.  No author or distributor accepts responsibility to anyone for
  24. //    the consequences of using it or for whether it serves any particular
  25. //    purpose or works at all, unless he says so in writing.  Refer to the
  26. //    CHESS General Public License for full details.
  27. //
  28. //    Everyone is granted permission to copy, modify and redistribute CHESS,
  29. //    but only under the conditions described in the CHESS General Public
  30. //    License.  A copy of this license is supposed to have been given to you
  31. //    along with CHESS so you can know your rights and responsibilities.  It
  32. //    should be in a file named COPYING.  Among other things, the copyright
  33. //    notice and this notice must be preserved on all copies.
  34. //
  35.  
  36. #define INCL_DOS
  37. #define INCL_PM
  38. #include <os2.h>
  39. #include <string.h>
  40. #include <time.h>
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include "PmChess.h"
  44. #include "GnuChess.h"
  45. #include "Defs.h"
  46.  
  47.  
  48. #if ttblsz
  49. extern unsigned long hashkey, hashbd;
  50. extern struct hashval far hashcode[2][7][64];
  51.  
  52. #ifdef M_I386
  53. extern struct hashentry ttable[2][ttblsz];
  54. #else
  55. extern struct hashentry far ttable[2][ttblsz];
  56. #endif
  57.  
  58. #endif /* ttblsz */
  59.  
  60. extern unsigned char far history[8192];
  61.  
  62. extern short rpthash[2][256];
  63. extern unsigned char far nextpos[8][64][64];
  64. extern unsigned char far nextdir[8][64][64];
  65.  
  66. extern short FROMsquare, TOsquare, Zscore, zwndw;
  67. extern unsigned short PV, Swag0, Swag1, Swag2, Swag3, Swag4;
  68. extern unsigned short killr0[maxdepth], killr1[maxdepth];
  69. extern unsigned short killr2[maxdepth], killr3[maxdepth];
  70. extern short Pscore[maxdepth], Tscore[maxdepth];
  71. extern unsigned long hashkey, hashbd;
  72. extern short ChkFlag[maxdepth], CptrFlag[maxdepth], PawnThreat[maxdepth];
  73. extern short mtl[2], pmtl[2], emtl[2], hung[2];
  74. extern short player, xwndw, rehash;
  75. extern short PieceCnt[2];
  76. extern long NodeCnt, ETnodes, EvalNodes, HashCnt, FHashCnt, HashCol;
  77. extern short HasKnight[2], HasBishop[2], HasRook[2], HasQueen[2];
  78. extern short Pindex[64];
  79.  
  80. static short rank7[3] = {6, 1, 0};
  81. static short kingP[3] = {4, 60, 0};
  82. static short value[7] =
  83. {0, valueP, valueN, valueB, valueR, valueQ, valueK};
  84.  
  85. static short sweep[8] =
  86. {false, false, false, true, true, true, false, false};
  87.  
  88. static short ptype[2][8] = {
  89.   no_piece, pawn, knight, bishop, rook, queen, king, no_piece,
  90.   no_piece, bpawn, knight, bishop, rook, queen, king, no_piece};
  91.  
  92. static short control[7] =
  93. {0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK};
  94.  
  95. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  96.  
  97. void
  98. pick (short int p1, short int p2)
  99.  
  100. /*
  101.   Find the best move in the tree between indexes p1 and p2. Swap the best
  102.   move into the p1 element.
  103. */
  104.  
  105. {
  106.   register short p, s;
  107.   short p0, s0;
  108.   struct leaf temp;
  109.  
  110.   s0 = Tree[p1].score;
  111.   p0 = p1;
  112.   for (p = p1 + 1; p <= p2; p++)
  113.     if ((s = Tree[p].score) > s0)
  114.       {
  115.         s0 = s;
  116.         p0 = p;
  117.       }
  118.   if (p0 != p1)
  119.     {
  120.       temp = Tree[p1];
  121.       Tree[p1] = Tree[p0];
  122.       Tree[p0] = temp;
  123.     }
  124. }
  125.  
  126. void
  127. SelectMove (HWND hWnd, short int side, short int iop)
  128.  
  129. /*
  130.   Select a move by calling function search() at progressively deeper ply
  131.   until time is up or a mate or draw is reached. An alpha-beta window of -90
  132.   to +90 points is set around the score returned from the previous
  133.   iteration. If Sdepth != 0 then the program has correctly predicted the
  134.   opponents move and the search will start at a depth of Sdepth+1 rather
  135.   than a depth of 1.
  136. */
  137.  
  138. {
  139.   static short tempb, tempc, tempsf, tempst, xside, rpt;
  140.   static short alpha, beta, score;
  141.   register short i;
  142.  
  143.  
  144.   flag.timeout = false;
  145.   xside = otherside[side];
  146.   if (iop != 2)
  147.     player = side;
  148.   if (TCflag)
  149.     {
  150.       if ((TimeControl.moves[side] + 3) != 0)
  151.         ResponseTime = (TimeControl.clock[side]) /
  152.           (TimeControl.moves[side] + 3) -
  153.           OperatorTime;
  154.       else
  155.         ResponseTime = 0;
  156.       ResponseTime += (ResponseTime * TimeControl.moves[side]) / (2 * TCmoves + 1);
  157.     }
  158.   else
  159.     ResponseTime = Level;
  160.   if (iop == 2)
  161.     ResponseTime = 99999;
  162.   if (Sdepth > 0 && root->score > Zscore - zwndw)
  163.     ResponseTime -= ft;
  164.   else if (ResponseTime < 1)
  165.     ResponseTime = 1;
  166.   ExtraTime = 0;
  167.   ExaminePosition ();
  168.   ScorePosition (side, &score);
  169.   /* Pscore[0] = -score; */
  170.   ShowSidetoMove ();
  171.  
  172.   if (Sdepth == 0)
  173.     {
  174. #if ttblsz
  175.       /* ZeroTTable (); */
  176. #endif /* ttblsz */
  177.       SearchStartStuff (side);
  178.       _fmemset(history, 0, sizeof(history));
  179.       FROMsquare = TOsquare = -1;
  180.       PV = 0;
  181.       if (iop != 2)
  182.         hint = 0;
  183.       for (i = 0; i < maxdepth; i++)
  184.         PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  185.       alpha = score - 90;
  186.       beta = score + 90;
  187.       rpt = 0;
  188.       TrPnt[1] = 0;
  189.       root = &Tree[0];
  190.       MoveList (side, 1);
  191.       for (i = TrPnt[1]; i < TrPnt[2]; i++)
  192.         pick (i, TrPnt[2] - 1);
  193.       if (Book != NULL)
  194.         OpeningBook (&hint);
  195.       if (Book != NULL)
  196.         flag.timeout = true;
  197.       NodeCnt = ETnodes = EvalNodes = HashCnt = FHashCnt = HashCol = 0;
  198.       Zscore = 0;
  199.       zwndw = 20;
  200.     }
  201.   while (!flag.timeout && Sdepth < MaxSearchDepth)
  202.     {
  203.       Sdepth++;
  204.       ShowDepth (' ');
  205.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  206.       for (i = 1; i <= Sdepth; i++)
  207.         killr0[i] = PrVar[i];
  208.       if (score < alpha)
  209.         {
  210.           ShowDepth ('-');
  211.           ExtraTime = 10 * ResponseTime;
  212.           /* ZeroTTable (); */
  213.           score = search (side, 1, Sdepth, -9000, score, PrVar, &rpt);
  214.         }
  215.       if (score > beta && !(root->flags & exact))
  216.         {
  217.           ShowDepth ('+');
  218.           ExtraTime = 0;
  219.           /* ZeroTTable (); */
  220.           score = search (side, 1, Sdepth, score, 9000, PrVar, &rpt);
  221.         }
  222.       score = root->score;
  223.       if (!flag.timeout)
  224.         for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
  225.           pick (i, TrPnt[2] - 1);
  226.       ShowResults (score, PrVar, '.');
  227.       for (i = 1; i <= Sdepth; i++)
  228.         killr0[i] = PrVar[i];
  229.       if (score > Zscore - zwndw && score > Tree[1].score + 250)
  230.         ExtraTime = 0;
  231.       else if (score > Zscore - 3 * zwndw)
  232.         ExtraTime = ResponseTime;
  233.       else
  234.         ExtraTime = 3 * ResponseTime;
  235.       if (root->flags & exact)
  236.         flag.timeout = true;
  237.       if (Tree[1].score < -9000)
  238.         flag.timeout = true;
  239.       if (4 * et > 2 * ResponseTime + ExtraTime)
  240.         flag.timeout = true;
  241.       if (!flag.timeout)
  242.         {
  243.           Tscore[0] = score;
  244.           if (Zscore == 0)
  245.             Zscore = score;
  246.           else
  247.             Zscore = (Zscore + score) / 2;
  248.         }
  249.       zwndw = 20 + abs (Zscore / 12);
  250.       beta = score + Bwindow;
  251.       if (Zscore < score)
  252.         alpha = Zscore - Awindow - zwndw;
  253.       else
  254.         alpha = score - Awindow - zwndw;
  255.     }
  256.  
  257.   score = root->score;
  258.   if (rpt >= 2 || score < -12000)
  259.     root->flags |= draw;
  260.   if (iop == 2)
  261.     return;
  262.   if (Book == NULL)
  263.     hint = PrVar[2];
  264.   ElapsedTime (1);
  265.  
  266.   if (score > -9999 && rpt <= 2)
  267.     {
  268.       MakeMove (side, root, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  269.       algbr (root->f, root->t, (short) root->flags);
  270.     }
  271.   else
  272.     algbr (0, 0, 0);
  273.   OutputMove (hWnd);
  274.   if (score == -9999 || score == 9998)
  275.     flag.mate = true;
  276.   if (flag.mate)
  277.     hint = 0;
  278.   if ((board[root->t] == pawn)
  279.       || (root->flags & capture)
  280.       || (root->flags & cstlmask))
  281.     {
  282.       Game50 = GameCnt;
  283.       ZeroRPT ();
  284.     }
  285.   GameList[GameCnt].score = score;
  286.   GameList[GameCnt].nodes = NodeCnt;
  287.   GameList[GameCnt].time = (short) et;
  288.   GameList[GameCnt].depth = Sdepth;
  289.   if (TCflag)
  290.     {
  291.       TimeControl.clock[side] -= (et + OperatorTime);
  292.       if (--TimeControl.moves[side] == 0)
  293.         SetTimeControl ();
  294.     }
  295.   if ((root->flags & draw) && flag.bothsides)
  296.     flag.mate = true;
  297.   if (GameCnt > 470)
  298.     flag.mate = true; /* out of move store, you loose */
  299.   player = xside;
  300.   Sdepth = 0;
  301. }
  302.  
  303. inline void
  304. repetition (short int *cnt)
  305.  
  306. /*
  307.   Check for draw by threefold repetition.
  308. */
  309.  
  310. {
  311.   short i, c, f, t;
  312.   short b[64];
  313.   unsigned short m;
  314.  
  315.   *cnt = c = 0;
  316.   if (GameCnt > Game50 + 3)
  317.     {
  318. #ifdef NOMEMSET
  319.       for (i = 0; i < 64; b[i++] = 0) ;
  320. #else
  321.       memset ((char *) b, 0, sizeof (b));
  322. #endif /* NOMEMSET */
  323.       for (i = GameCnt; i > Game50; i--)
  324.         {
  325.           m = GameList[i].gmove;
  326.           f = m >> 8;
  327.           t = m & 0xFF;
  328.           if (++b[f] == 0)
  329.             c--;
  330.           else
  331.             c++;
  332.           if (--b[t] == 0)
  333.             c--;
  334.           else
  335.             c++;
  336.           if (c == 0)
  337.             (*cnt)++;
  338.         }
  339.     }
  340. }
  341.  
  342. int
  343. search (short int side,
  344.         short int ply,
  345.         short int depth,
  346.         short int alpha,
  347.         short int beta,
  348.         short unsigned int *bstline,
  349.         short int *rpt)
  350.  
  351. /*
  352.   Perform an alpha-beta search to determine the score for the current board
  353.   position. If depth <= 0 only capturing moves, pawn promotions and
  354.   responses to check are generated and searched, otherwise all moves are
  355.   processed. The search depth is modified for check evasions, certain
  356.   re-captures and threats. Extensions may continue for up to 11 ply beyond
  357.   the nominal search depth.
  358. */
  359.  
  360. #define UpdateSearchStatus \
  361. {\
  362.    if (flag.post) ShowCurrentMove(pnt,node->f,node->t);\
  363.      if (pnt > TrPnt[1])\
  364.        {\
  365.           d = best-Zscore; e = best-node->score;\
  366.             if (best < alpha) ExtraTime = 10*ResponseTime;\
  367.             else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
  368.             else if (d > -zwndw) ExtraTime = 0;\
  369.             else if (d > -3*zwndw) ExtraTime = ResponseTime;\
  370.             else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
  371.             else ExtraTime = 5*ResponseTime;\
  372.             }\
  373.             }
  374. #define prune (cf && score+node->score < alpha)
  375. #define ReCapture (flag.rcptr && score > alpha && score < beta &&\
  376.                    ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
  377. /* && depth == Sdepth-ply+1 */
  378. #define Parry (hung[side] > 1 && ply == Sdepth+1)
  379. #define MateThreat (ply < Sdepth+4 && ply > 4 &&\
  380.                     ChkFlag[ply-2] && ChkFlag[ply-4] &&\
  381.                     ChkFlag[ply-2] != ChkFlag[ply-4])
  382.  
  383. {
  384.   register short j, pnt;
  385.   short best, tempb, tempc, tempsf, tempst;
  386.   short xside, pbst, d, e, cf, score, rcnt, slk, InChk;
  387.   unsigned short mv, nxtline[maxdepth];
  388.   struct leaf far *node, tmp;
  389.  
  390.   NodeCnt++;
  391.   xside = otherside[side];
  392.  
  393.   if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  394.     repetition (rpt);
  395.   else
  396.     *rpt = 0;
  397.   /* Detect repetitions a bit earlier. SMC. 12/89 */
  398.   if (*rpt == 1 && ply > 1)
  399.     return (0);
  400.   /* if (*rpt >= 2) return(0); */
  401.  
  402.   score = evaluate (side, ply, alpha, beta, INCscore, &slk, &InChk);
  403.   if (score > 9000)
  404.     {
  405.       bstline[ply] = 0;
  406.       return (score);
  407.     }
  408.   if (depth > 0)
  409.     {
  410.       /* Allow opponent a chance to check again */
  411.       if (InChk)
  412.         depth = (depth < 2) ? 2 : depth;
  413.       else if (PawnThreat[ply - 1] || ReCapture)
  414.         ++depth;
  415.     }
  416.   else
  417.     {
  418.       if (score >= alpha &&
  419.           (InChk || PawnThreat[ply - 1] || Parry))
  420.         depth = 1;
  421.       else if (score <= beta && MateThreat)
  422.         depth = 1;
  423.     }
  424.  
  425. #if ttblsz
  426.   if (depth > 0 && flag.hash && ply > 1)
  427.     {
  428.       if (ProbeTTable (side, depth, &alpha, &beta, &score) == false)
  429. #ifdef HASHFILE 
  430.         if (hashfile && (depth > 5) && (GameCnt < 12))
  431.           ProbeFTable (side, depth, &alpha, &beta, &score);
  432. #else
  433.       /* do nothing */;
  434. #endif /* HASHFILE */      
  435.       bstline[ply] = PV;
  436.       bstline[ply + 1] = 0;
  437.       if (beta == -20000)
  438.         return (score);
  439.       if (alpha > beta)
  440.         return (alpha);
  441.     }
  442. #endif /* ttblsz */
  443.   if (Sdepth == 1)
  444.     d = 7;
  445.   else
  446.     d = 11;
  447.   if (ply > Sdepth + d || (depth < 1 && score > beta))
  448.     /* score >= beta ?? */
  449.     return (score);
  450.  
  451.   if (ply > 1)
  452.     if (depth > 0)
  453.       MoveList (side, ply);
  454.     else
  455.       CaptureList (side, ply);
  456.  
  457.   if (TrPnt[ply] == TrPnt[ply + 1])
  458.     return (score);
  459.  
  460.   cf = (depth < 1 && ply > Sdepth + 1 && !ChkFlag[ply - 2] && !slk);
  461.  
  462.   if (depth > 0)
  463.     best = -12000;
  464.   else
  465.     best = score;
  466.   if (best > alpha)
  467.     alpha = best;
  468.  
  469.   for (pnt = pbst = TrPnt[ply];
  470.        pnt < TrPnt[ply + 1] && best <= beta;    /* best < beta ?? */
  471.        pnt++)
  472.     {
  473.  
  474.       {
  475.       QMSG qmsg;
  476.  
  477.       while (!flag.timeout && WinPeekMsg(hab, &qmsg, NULL, 0, 0, PM_REMOVE))
  478.         WinDispatchMsg(hab, &qmsg);
  479.       }
  480.  
  481.       if (ply > 1)
  482.         pick (pnt, TrPnt[ply + 1] - 1);
  483.       node = &Tree[pnt];
  484.       mv = (node->f << 8) | node->t;
  485.       nxtline[ply + 1] = 0;
  486.  
  487.       if (prune)
  488.         break;
  489.       if (ply == 1)
  490.         UpdateSearchStatus;
  491.  
  492.       if (!(node->flags & exact))
  493.         {
  494.           MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  495.           CptrFlag[ply] = (node->flags & capture);
  496.           PawnThreat[ply] = (node->flags & pwnthrt);
  497.           Tscore[ply] = node->score;
  498.           PV = node->reply;
  499.           node->score = -search (xside, ply + 1,
  500.                                  (depth > 0) ? depth - 1 : 0,
  501.                                  -beta, -alpha,
  502.                                  nxtline, &rcnt);
  503.           if (abs (node->score) > 9000)
  504.             node->flags |= exact;
  505.           else if (rcnt == 1)
  506.             node->score /= 2;
  507.           if (rcnt >= 2 || GameCnt - Game50 > 99 ||
  508.               (node->score == 9999 - ply && !ChkFlag[ply]))
  509.             {
  510.               node->flags |= draw;
  511.               node->flags |= exact;
  512.               if (side == computer)
  513.                 node->score = contempt;
  514.               else
  515.                 node->score = -contempt;
  516.             }
  517.           node->reply = nxtline[ply + 1];
  518.           UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  519.         }
  520.       if (node->score > best && !flag.timeout)
  521.         {
  522.           if (depth > 0)
  523.             if (node->score > alpha && !(node->flags & exact))
  524.               node->score += depth;
  525.           best = node->score;
  526.           pbst = pnt;
  527.           if (best > alpha)
  528.             alpha = best;
  529.           for (j = ply + 1; nxtline[j] > 0; j++)
  530.             bstline[j] = nxtline[j];
  531.           bstline[j] = 0;
  532.           bstline[ply] = mv;
  533.           if (ply == 1)
  534.             {
  535.               if (best > root->score)
  536.                 {
  537.                   tmp = Tree[pnt];
  538.                   for (j = pnt - 1; j >= 0; j--)
  539.                     Tree[j + 1] = Tree[j];
  540.                   Tree[0] = tmp;
  541.                   pbst = 0;
  542.                 }
  543.               if (Sdepth > 2)
  544.                 if (best > beta)
  545.                   ShowResults (best, bstline, '+');
  546.                 else if (best < alpha)
  547.                   ShowResults (best, bstline, '-');
  548.                 else
  549.                   ShowResults (best, bstline, '&');
  550.             }
  551.         }
  552.       if (NodeCnt > ETnodes)
  553.         ElapsedTime (0);
  554.       if (flag.timeout)
  555.         return (-Tscore[ply - 1]);
  556.     }
  557.  
  558.   node = &Tree[pbst];
  559.   mv = (node->f << 8) | node->t;
  560. #if ttblsz
  561.   if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  562.     {
  563.       PutInTTable (side, best, depth, alpha, beta, mv);
  564. #ifdef HASHFILE      
  565.       if (hashfile && (depth > 5) && (GameCnt < 12))
  566.         PutInFTable (side, best, depth, alpha, beta, node->f, node->t);
  567. #endif /* HASHFILE */      
  568.     }
  569. #endif /* ttblsz */
  570.   if (depth > 0)
  571.     {
  572.       j = (node->f << 6) | node->t;
  573.       if (side == black)
  574.         j |= 0x1000;
  575. /*      if (history[j] < 150)
  576.           history[j] += (unsigned char) 2 * depth; */
  577.       if (*(history+j) < 150)
  578.         *(history+j) += (unsigned char) 2 * depth;
  579.       if ((SHORT)node->t != (SHORT)(GameList[GameCnt].gmove & 0xFF))
  580.         if (best <= beta)
  581.           killr3[ply] = mv;
  582.         else if (mv != killr1[ply])
  583.           {
  584.             killr2[ply] = killr1[ply];
  585.             killr1[ply] = mv;
  586.           }
  587.       if (best > 9000)
  588.         killr0[ply] = mv;
  589.       else
  590.         killr0[ply] = 0;
  591.     }
  592.   return (best);
  593. }
  594.  
  595. #if ttblsz
  596. /*
  597.   hashbd contains a 32 bit "signature" of the board position. hashkey
  598.   contains a 16 bit code used to address the hash table. When a move is
  599.   made, XOR'ing the hashcode of moved piece on the from and to squares with
  600.   the hashbd and hashkey values keeps things current.
  601. */
  602. #define UpdateHashbd(side, piece, f, t) \
  603. {\
  604.   if ((f) >= 0)\
  605.     {\
  606.       hashbd ^= hashcode[side][piece][f].bd; \
  607.       hashkey ^= hashcode[side][piece][f].key; \
  608.     }\
  609.   if ((t) >= 0)\
  610.     {\
  611.       hashbd ^= hashcode[side][piece][t].bd; \
  612.       hashkey ^= hashcode[side][piece][t].key; \
  613.     }\
  614. }
  615.  
  616. #define CB(i) (unsigned char) ((color[2 * (i)] ? 0x80 : 0)\
  617.                | (board[2 * (i)] << 4)\
  618.                | (color[2 * (i) + 1] ? 0x8 : 0)\
  619.                | (board[2 * (i) + 1]))
  620.  
  621. int
  622. ProbeTTable (short int side,
  623.              short int depth,
  624.              short int *alpha,
  625.              short int *beta,
  626.              short int *score)
  627.  
  628. /*
  629.   Look for the current board position in the transposition table.
  630. */
  631.  
  632. {
  633.   struct hashentry far *ptbl;
  634.   register unsigned short i;
  635.  
  636.   ptbl = &ttable[side][hashkey & (ttblsz - 1)];
  637.  
  638.   /* rehash max rehash times */
  639.   for (i = 1; ptbl->hashbd != hashbd && i <= (USHORT)rehash; i++)
  640.     ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)];
  641.   if ((short) ptbl->depth >= depth && ptbl->hashbd == hashbd)
  642.     {
  643.       HashCnt++;
  644. #ifdef HASHTEST
  645.       for (i = 0; i < 32; i++)
  646.         {
  647.           if (ptbl->bd[i] != CB(i))
  648.             {
  649.               HashCol++;
  650.               ShowMessage("ttable collision detected");
  651.               break;
  652.             }
  653.         }
  654. #endif /* HASHTEST */
  655.  
  656.       PV = ptbl->mv;
  657.       if (ptbl->flags & truescore)
  658.         {
  659.           *score = ptbl->score;
  660.           *beta = -20000;
  661.         }
  662. #if 0 /* commented out, why? */
  663.       else if (ptbl->flags & upperbound)
  664.         {
  665.           if (ptbl->score < *beta) *beta = ptbl->score+1;
  666.         }
  667. #endif
  668.       else if (ptbl->flags & lowerbound)
  669.         {
  670.           if (ptbl->score > *alpha)
  671.             *alpha = ptbl->score - 1;
  672.         }
  673.       return(true);
  674.     }
  675.   return(false);
  676. }
  677.  
  678. void
  679. PutInTTable (short int side,
  680.              short int score,
  681.              short int depth,
  682.              short int alpha,
  683.              short int beta,
  684.              short unsigned int mv)
  685.  
  686. /*
  687.   Store the current board position in the transposition table.
  688. */
  689.  
  690. {
  691.   struct hashentry far *ptbl;
  692.   register unsigned short i;
  693.  
  694.   ptbl = &ttable[side][hashkey & (ttblsz - 1)];
  695.  
  696.   /* rehash max rehash times */
  697.   for (i = 1; depth < (SHORT)ptbl->depth && ptbl->hashbd != hashbd && i <= (USHORT)rehash; i++)
  698.     ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)];
  699.   if (depth >= (SHORT)ptbl->depth || ptbl->hashbd != hashbd)
  700.     {
  701.       ptbl->hashbd = hashbd;
  702.       ptbl->depth = (unsigned char) depth;
  703.       ptbl->score = score;
  704.       ptbl->mv = mv;
  705.       ptbl->flags = 0;
  706.       if (score < alpha)
  707.         ptbl->flags |= upperbound;
  708.       else if (score > beta)
  709.         ptbl->flags |= lowerbound;
  710.       else
  711.         ptbl->flags |= truescore;
  712. #ifdef HASHTEST
  713.       for (i = 0; i < 32; i++)
  714.         {
  715.           ptbl->bd[i] = CB(i);
  716.         }
  717. #endif /* HASHTEST */
  718.     }
  719. }
  720.  
  721. void
  722. ZeroTTable (void)
  723. {
  724.   register int side, i;
  725.  
  726.   if (flag.hash)
  727.     for (side = white; side <= black; side++)
  728.       for (i = 0; i < ttblsz; i++)
  729.         ttable[side][i].depth = 0;
  730. }
  731.  
  732. #ifdef HASHFILE
  733. int
  734. ProbeFTable(short int side,
  735.             short int depth,
  736.             short int *alpha,
  737.             short int *beta,
  738.             short int *score)
  739.  
  740. /*
  741.   Look for the current board position in the persistent transposition table.
  742. */
  743.  
  744. {
  745.   register unsigned short i, j;
  746.   unsigned long hashix;
  747.   short s;
  748.   struct fileentry new, t;
  749.  
  750.   if (side == white)
  751.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  752.   else
  753.     hashix = hashkey | 1 & (filesz - 1);
  754.  
  755.   for (i = 0; i < 32; i++)
  756.     new.bd[i] = CB(i);
  757.   new.flags = 0;
  758.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  759.     new.flags |= queencastle;
  760.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  761.     new.flags |= kingcastle;
  762.  
  763.   for (i = 0; i < frehash; i++)
  764.     {
  765.       fseek(hashfile,
  766.             sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  767.             SEEK_SET);
  768.       fread(&t, sizeof(struct fileentry), 1, hashfile);
  769.       for (j = 0; j < 32; j++)
  770.         if (t.bd[j] != new.bd[j])
  771.           break;
  772.       if (((short) t.depth >= depth) && (j >= 32)
  773.           && (new.flags == (t.flags & (kingcastle | queencastle))))
  774.         {
  775.           FHashCnt++;
  776.           PV = (t.f << 8) | t.t;
  777.           s = (t.sh << 8) | t.sl;
  778.           if (t.flags & truescore)
  779.             {
  780.               *score = s;
  781.               *beta = -20000;
  782.             }
  783.           else if (t.flags & lowerbound)
  784.             {
  785.               if (s > *alpha)
  786.                 *alpha = s - 1;
  787.             }
  788.           return(true);
  789.         }
  790.     }
  791.   return(false);
  792. }
  793.  
  794. void
  795. PutInFTable (short int side,
  796.              short int score,
  797.              short int depth,
  798.              short int alpha,
  799.              short int beta,
  800.              short unsigned int f,
  801.              short unsigned int t)
  802.  
  803. /*
  804.   Store the current board position in the persistent transposition table.
  805. */
  806.  
  807. {
  808.   register unsigned short i;
  809.   unsigned long hashix;
  810.   struct fileentry new, tmp;
  811.  
  812.   if (side == white)
  813.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  814.   else
  815.     hashix = hashkey | 1 & (filesz - 1);
  816.  
  817.   for (i = 0; i < 32; i++)
  818.     new.bd[i] = CB(i);
  819.   new.f = (unsigned char) f;
  820.   new.t = (unsigned char) t;
  821.   new.flags = 0;
  822.   if (score < alpha)
  823.     new.flags |= upperbound;
  824.   else if (score > beta)
  825.     new.flags |= lowerbound;
  826.   else
  827.     new.flags |= truescore;
  828.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  829.     new.flags |= queencastle;
  830.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  831.     new.flags |= kingcastle;
  832.   new.depth = (unsigned char) depth;
  833.   new.sh = (unsigned char) (score >> 8);
  834.   new.sl = (unsigned char) (score & 0xFF);
  835.  
  836.   for (i = 0; i < frehash; i++)
  837.     {
  838.       fseek(hashfile,
  839.             sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  840.             SEEK_SET);
  841.       fread(&tmp, sizeof(struct fileentry), 1, hashfile);
  842.       if ((short) tmp.depth <= depth)
  843.         {
  844.           fseek(hashfile,
  845.                 sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  846.                 SEEK_SET);
  847.           fwrite (&new, sizeof(struct fileentry), 1, hashfile);
  848.           break;
  849.         }
  850.     }
  851. }
  852. #endif /* HASHFILE */
  853. #endif /* ttblsz */
  854.  
  855. void
  856. ZeroRPT (void)
  857. {
  858.   register int side, i;
  859.  
  860.   for (side = white; side <= black; side++)
  861.     for (i = 0; i < 256; i++)
  862.       rpthash[side][i] = 0;
  863. }
  864.  
  865. #define Link(from,to,flag,s) \
  866. {\
  867.    node->f = from; node->t = to;\
  868.      node->reply = 0;\
  869.        node->flags = flag;\
  870.          node->score = s;\
  871.            ++node;\
  872.              ++TrPnt[ply+1];\
  873.              }
  874.  
  875. static inline void
  876. LinkMove (short int ply,
  877.           short int f,
  878.           short int t,
  879.           short int flag,
  880.           short int xside)
  881.  
  882. /*
  883.   Add a move to the tree.  Assign a bonus to order the moves
  884.   as follows:
  885.   1. Principle variation
  886.   2. Capture of last moved piece
  887.   3. Other captures (major pieces first)
  888.   4. Killer moves
  889.   5. "history" killers
  890. */
  891.  
  892. {
  893.   register short s, z;
  894.   unsigned short mv;
  895.   struct leaf far *node;
  896.  
  897.   node = &Tree[TrPnt[ply + 1]];
  898.   mv = (f << 8) | t;
  899.   s = 0;
  900.   if (mv == Swag0)
  901.     s = 2000;
  902.   else if (mv == Swag1)
  903.     s = 60;
  904.   else if (mv == Swag2)
  905.     s = 50;
  906.   else if (mv == Swag3)
  907.     s = 40;
  908.   else if (mv == Swag4)
  909.     s = 30;
  910.   z = (f << 6) | t;
  911.   if (xside == white)
  912.     z |= 0x1000;
  913.   s += history[z];
  914.   if (color[t] != neutral)
  915.     {
  916.       if (t == TOsquare)
  917.         s += 500;
  918.       s += value[board[t]] - board[f];
  919.     }
  920.   if (board[f] == pawn)
  921.     if (row (t) == 0 || row (t) == 7)
  922.       {
  923.         flag |= promote;
  924.         s += 800;
  925.         Link (f, t, flag | queen, s - 20000);
  926.         s -= 200;
  927.         Link (f, t, flag | knight, s - 20000);
  928.         s -= 50;
  929.         Link (f, t, flag | rook, s - 20000);
  930.         flag |= bishop;
  931.         s -= 50;
  932.       }
  933.     else if (row (t) == 1 || row (t) == 6)
  934.       {
  935.         flag |= pwnthrt;
  936.         s += 600;
  937.       }
  938.   Link (f, t, flag, s - 20000);
  939. }
  940.  
  941.  
  942. static inline void
  943. GenMoves (short int ply, short int sq, short int side, short int xside)
  944.  
  945. /*
  946.   Generate moves for a piece. The moves are taken from the precalulated
  947.   array nextpos/nextdir. If the board is free, next move is choosen from
  948.   nextpos else from nextdir.
  949. */
  950.  
  951. {
  952.   unsigned char far *ppos, far *pdir;
  953.   register short u, piece;
  954.  
  955.   piece = board[sq];
  956.   ppos = nextpos[ptype[side][piece]][sq];
  957.   pdir = nextdir[ptype[side][piece]][sq];
  958.   if (piece == pawn)
  959.     {
  960.       u = ppos[sq];     /* follow no captures thread */
  961.       if (color[u] == neutral)
  962.         {
  963.           LinkMove (ply, sq, u, 0, xside);
  964.           u = ppos[u];
  965.           if (color[u] == neutral)
  966.             LinkMove (ply, sq, u, 0, xside);
  967.         }
  968.       u = pdir[sq];     /* follow captures thread */
  969.       if (color[u] == xside)
  970.         LinkMove (ply, sq, u, capture, xside);
  971.       else
  972.         if (u == epsquare)
  973.           LinkMove (ply, sq, u, capture | epmask, xside);
  974.       u = pdir[u];
  975.       if (color[u] == xside)
  976.         LinkMove (ply, sq, u, capture, xside);
  977.       else
  978.         if (u == epsquare)
  979.           LinkMove (ply, sq, u, capture | epmask, xside);
  980.     }
  981.   else
  982.     {
  983.       u = ppos[sq];
  984.       do
  985.         {
  986.           if (color[u] == neutral)
  987.             {
  988.               LinkMove (ply, sq, u, 0, xside);
  989.               u = ppos[u];
  990.             }
  991.           else
  992.             {
  993.               if (color[u] == xside)
  994.                 LinkMove (ply, sq, u, capture, xside);
  995.               u = pdir[u];
  996.             }
  997.       } while (u != sq);
  998.     }
  999. }
  1000.  
  1001. void
  1002. MoveList (short int side, short int ply)
  1003.  
  1004. /*
  1005.   Fill the array Tree[] with all available moves for side to play. Array
  1006.   TrPnt[ply] contains the index into Tree[] of the first move at a ply.
  1007. */
  1008.  
  1009. {
  1010.   short xside;
  1011.   register short i, f;
  1012.  
  1013.   xside = otherside[side];
  1014.   TrPnt[ply + 1] = TrPnt[ply];
  1015.   if (PV == 0)
  1016.     Swag0 = killr0[ply];
  1017.   else
  1018.     Swag0 = PV;
  1019.   Swag1 = killr1[ply];
  1020.   Swag2 = killr2[ply];
  1021.   Swag3 = killr3[ply];
  1022.   if (ply > 2)
  1023.     Swag4 = killr1[ply - 2];
  1024.   else
  1025.     Swag4 = 0;
  1026.   for (i = PieceCnt[side]; i >= 0; i--)
  1027.     GenMoves (ply, PieceList[side][i], side, xside);
  1028.   if (!castld[side])
  1029.     {
  1030.       f = PieceList[side][0];
  1031.       if (castle (side, f, f + 2, 0))
  1032.         {
  1033.           LinkMove (ply, f, f + 2, cstlmask, xside);
  1034.         }
  1035.       if (castle (side, f, f - 2, 0))
  1036.         {
  1037.           LinkMove (ply, f, f - 2, cstlmask, xside);
  1038.         }
  1039.     }
  1040. }
  1041.  
  1042. void
  1043. CaptureList (short int side, short int ply)
  1044.  
  1045. /*
  1046.   Fill the array Tree[] with all available cature and promote moves for
  1047.   side to play. Array TrPnt[ply] contains the index into Tree[]
  1048.   of the first move at a ply.
  1049. */
  1050.  
  1051. {
  1052.   short u, sq, xside;
  1053.   struct leaf far *node;
  1054.   unsigned char far *ppos, far *pdir;
  1055.   short piece, *PL, r7;
  1056.   register short i;
  1057.  
  1058.  
  1059.   xside = otherside[side];
  1060.   TrPnt[ply + 1] = TrPnt[ply];
  1061.   node = &Tree[TrPnt[ply]];
  1062.   r7 = rank7[side];
  1063.   PL = PieceList[side];
  1064.   for (i = 0; i <= PieceCnt[side]; i++)
  1065.     {
  1066.       sq = PL[i];
  1067.       piece = board[sq];
  1068.       if (sweep[piece])
  1069.         {
  1070.           ppos = nextpos[piece][sq];
  1071.           pdir = nextdir[piece][sq];
  1072.           u = ppos[sq];
  1073.           do
  1074.             {
  1075.               if (color[u] == neutral)
  1076.                 u = ppos[u];
  1077.               else
  1078.                 {
  1079.                   if (color[u] == xside)
  1080.                     Link (sq, u, capture,
  1081.                           value[board[u]] + svalue[board[u]] - piece);
  1082.                   u = pdir[u];
  1083.                 }
  1084.           } while (u != sq);
  1085.         }
  1086.       else
  1087.         {
  1088.           pdir = nextdir[ptype[side][piece]][sq];
  1089.           if (piece == pawn && row (sq) == r7)
  1090.             {
  1091.               u = pdir[sq];
  1092.               if (color[u] == xside)
  1093.                 Link (sq, u, capture | promote | queen, valueQ);
  1094.               u = pdir[u];
  1095.               if (color[u] == xside)
  1096.                 Link (sq, u, capture | promote | queen, valueQ);
  1097.               ppos = nextpos[ptype[side][piece]][sq];
  1098.               u = ppos[sq]; /* also generate non capture promote */
  1099.               if (color[u] == neutral)
  1100.                 Link (sq, u, promote | queen, valueQ);
  1101.             }
  1102.           else
  1103.             {
  1104.               u = pdir[sq];
  1105.               do
  1106.                 {
  1107.                   if (color[u] == xside)
  1108.                     Link (sq, u, capture,
  1109.                           value[board[u]] + svalue[board[u]] - piece);
  1110.                   u = pdir[u];
  1111.               } while (u != sq);
  1112.             }
  1113.         }
  1114.     }
  1115. }
  1116.  
  1117.  
  1118. int
  1119. castle (short int side, short int kf, short int kt, short int iop)
  1120.  
  1121. /* Make or Unmake a castling move. */
  1122.  
  1123. {
  1124.   short rf, rt, t0, xside;
  1125.  
  1126.   xside = otherside[side];
  1127.   if (kt > kf)
  1128.     {
  1129.       rf = kf + 3;
  1130.       rt = kt - 1;
  1131.     }
  1132.   else
  1133.     {
  1134.       rf = kf - 4;
  1135.       rt = kt + 1;
  1136.     }
  1137.   if (iop == 0)
  1138.     {
  1139.       if (kf != kingP[side] ||
  1140.           board[kf] != king ||
  1141.           board[rf] != rook ||
  1142.           Mvboard[kf] != 0 ||
  1143.           Mvboard[rf] != 0 ||
  1144.           color[kt] != neutral ||
  1145.           color[rt] != neutral ||
  1146.           color[kt - 1] != neutral ||
  1147.           SqAtakd (kf, xside) ||
  1148.           SqAtakd (kt, xside) ||
  1149.           SqAtakd (rt, xside))
  1150.         return (false);
  1151.     }
  1152.   else
  1153.     {
  1154.       if (iop == 1)
  1155.         {
  1156.           castld[side] = true;
  1157.           Mvboard[kf]++;
  1158.           Mvboard[rf]++;
  1159.         }
  1160.       else
  1161.         {
  1162.           castld[side] = false;
  1163.           Mvboard[kf]--;
  1164.           Mvboard[rf]--;
  1165.           t0 = kt;
  1166.           kt = kf;
  1167.           kf = t0;
  1168.           t0 = rt;
  1169.           rt = rf;
  1170.           rf = t0;
  1171.         }
  1172.       board[kt] = king;
  1173.       color[kt] = side;
  1174.       Pindex[kt] = 0;
  1175.       board[kf] = no_piece;
  1176.       color[kf] = neutral;
  1177.       board[rt] = rook;
  1178.       color[rt] = side;
  1179.       Pindex[rt] = Pindex[rf];
  1180.       board[rf] = no_piece;
  1181.       color[rf] = neutral;
  1182.       PieceList[side][Pindex[kt]] = kt;
  1183.       PieceList[side][Pindex[rt]] = rt;
  1184. #if ttblsz
  1185.       UpdateHashbd (side, king, kf, kt);
  1186.       UpdateHashbd (side, rook, rf, rt);
  1187. #endif /* ttblsz */
  1188.     }
  1189.   return (true);
  1190. }
  1191.  
  1192.  
  1193. static inline void
  1194. EnPassant (short int xside, short int f, short int t, short int iop)
  1195.  
  1196. /*
  1197.   Make or unmake an en passant move.
  1198. */
  1199.  
  1200. {
  1201.   register short l;
  1202.  
  1203.   if (t > f)
  1204.     l = t - 8;
  1205.   else
  1206.     l = t + 8;
  1207.   if (iop == 1)
  1208.     {
  1209.       board[l] = no_piece;
  1210.       color[l] = neutral;
  1211.     }
  1212.   else
  1213.     {
  1214.       board[l] = pawn;
  1215.       color[l] = xside;
  1216.     }
  1217.   InitializeStats ();
  1218. }
  1219.  
  1220.  
  1221. static inline void
  1222. UpdatePieceList (short int side, short int sq, short int iop)
  1223.  
  1224. /*
  1225.   Update the PieceList and Pindex arrays when a piece is captured or when a
  1226.   capture is unmade.
  1227. */
  1228.  
  1229. {
  1230.   register short i;
  1231.   if (iop == 1)
  1232.     {
  1233.       PieceCnt[side]--;
  1234.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1235.         {
  1236.           PieceList[side][i] = PieceList[side][i + 1];
  1237.           Pindex[PieceList[side][i]] = i;
  1238.         }
  1239.     }
  1240.   else
  1241.     {
  1242.       PieceCnt[side]++;
  1243.       PieceList[side][PieceCnt[side]] = sq;
  1244.       Pindex[sq] = PieceCnt[side];
  1245.     }
  1246. }
  1247.  
  1248. void
  1249. MakeMove (short int side,
  1250.           struct leaf far * node,
  1251.           short int *tempb,
  1252.           short int *tempc,
  1253.           short int *tempsf,
  1254.           short int *tempst,
  1255.           short int *INCscore)
  1256.  
  1257. /*
  1258.   Update Arrays board[], color[], and Pindex[] to reflect the new board
  1259.   position obtained after making the move pointed to by node. Also update
  1260.   miscellaneous stuff that changes when a move is made.
  1261. */
  1262.  
  1263. {
  1264.   short f, t, xside, ct, cf;
  1265.  
  1266.   xside = otherside[side];
  1267.   GameCnt++;
  1268.   f = node->f;
  1269.   t = node->t;
  1270.   epsquare = -1;
  1271.   FROMsquare = f;
  1272.   TOsquare = t;
  1273.   *INCscore = 0;
  1274.   GameList[GameCnt].gmove = (f << 8) | t;
  1275.   if (node->flags & cstlmask)
  1276.     {
  1277.       GameList[GameCnt].piece = no_piece;
  1278.       GameList[GameCnt].color = side;
  1279.       (void) castle (side, f, t, 1);
  1280.     }
  1281.   else
  1282.     {
  1283.       if (!(node->flags & capture) && (board[f] != pawn))
  1284.         rpthash[side][hashkey & 0xFF]++;
  1285.       *tempc = color[t];
  1286.       *tempb = board[t];
  1287.       *tempsf = svalue[f];
  1288.       *tempst = svalue[t];
  1289.       GameList[GameCnt].piece = *tempb;
  1290.       GameList[GameCnt].color = *tempc;
  1291.       if (*tempc != neutral)
  1292.         {
  1293.           UpdatePieceList (*tempc, t, 1);
  1294.           if (*tempb == pawn)
  1295.             --PawnCnt[*tempc][column (t)];
  1296.           if (board[f] == pawn)
  1297.             {
  1298.               --PawnCnt[side][column (f)];
  1299.               ++PawnCnt[side][column (t)];
  1300.               cf = column (f);
  1301.               ct = column (t);
  1302.               if (PawnCnt[side][ct] > 1 + PawnCnt[side][cf])
  1303.                 *INCscore -= 15;
  1304.               else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1305.                 *INCscore += 15;
  1306.               else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1307.                 *INCscore -= 15;
  1308.             }
  1309.           mtl[xside] -= value[*tempb];
  1310.           if (*tempb == pawn)
  1311.             pmtl[xside] -= valueP;
  1312. #if ttblsz
  1313.           UpdateHashbd (xside, *tempb, -1, t);
  1314. #endif /* ttblsz */
  1315.           *INCscore += *tempst;
  1316.           Mvboard[t]++;
  1317.         }
  1318.       color[t] = color[f];
  1319.       board[t] = board[f];
  1320.       svalue[t] = svalue[f];
  1321.       Pindex[t] = Pindex[f];
  1322.       PieceList[side][Pindex[t]] = t;
  1323.       color[f] = neutral;
  1324.       board[f] = no_piece;
  1325.       if (board[t] == pawn)
  1326.         if (t - f == 16)
  1327.           epsquare = f + 8;
  1328.         else if (f - t == 16)
  1329.           epsquare = f - 8;
  1330.       if (node->flags & promote)
  1331.         {
  1332.           board[t] = node->flags & pmask;
  1333.           if (board[t] == queen)
  1334.             HasQueen[side]++;
  1335.           else if (board[t] == rook)
  1336.             HasRook[side]++;
  1337.           else if (board[t] == bishop)
  1338.             HasBishop[side]++;
  1339.           else if (board[t] == knight)
  1340.             HasKnight[side]++;
  1341.           --PawnCnt[side][column (t)];
  1342.           mtl[side] += value[board[t]] - valueP;
  1343.           pmtl[side] -= valueP;
  1344. #if ttblsz
  1345.           UpdateHashbd (side, pawn, f, -1);
  1346.           UpdateHashbd (side, board[t], f, -1);
  1347. #endif /* ttblsz */
  1348.           *INCscore -= *tempsf;
  1349.         }
  1350.       if (node->flags & epmask)
  1351.         EnPassant (xside, f, t, 1);
  1352.       else
  1353. #if ttblsz
  1354.         UpdateHashbd (side, board[t], f, t);
  1355. #else
  1356.         /* NOOP */;     
  1357. #endif /* ttblsz */
  1358.       Mvboard[f]++;
  1359.     }
  1360. }
  1361.  
  1362. void
  1363. UnmakeMove (short int side,
  1364.             struct leaf far * node,
  1365.             short int *tempb,
  1366.             short int *tempc,
  1367.             short int *tempsf,
  1368.             short int *tempst)
  1369.  
  1370. /*
  1371.   Take back a move.
  1372. */
  1373.  
  1374. {
  1375.   short f, t, xside;
  1376.  
  1377.   xside = otherside[side];
  1378.   f = node->f;
  1379.   t = node->t;
  1380.   epsquare = -1;
  1381.   GameCnt--;
  1382.   if (node->flags & cstlmask)
  1383.     (void) castle (side, f, t, 2);
  1384.   else
  1385.     {
  1386.       color[f] = color[t];
  1387.       board[f] = board[t];
  1388.       svalue[f] = *tempsf;
  1389.       Pindex[f] = Pindex[t];
  1390.       PieceList[side][Pindex[f]] = f;
  1391.       color[t] = *tempc;
  1392.       board[t] = *tempb;
  1393.       svalue[t] = *tempst;
  1394.       if (node->flags & promote)
  1395.         {
  1396.           board[f] = pawn;
  1397.           ++PawnCnt[side][column (t)];
  1398.           mtl[side] += valueP - value[node->flags & pmask];
  1399.           pmtl[side] += valueP;
  1400. #if ttblsz
  1401.           UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  1402.           UpdateHashbd (side, pawn, -1, t);
  1403. #endif /* ttblsz */
  1404.         }
  1405.       if (*tempc != neutral)
  1406.         {
  1407.           UpdatePieceList (*tempc, t, 2);
  1408.           if (*tempb == pawn)
  1409.             ++PawnCnt[*tempc][column (t)];
  1410.           if (board[f] == pawn)
  1411.             {
  1412.               --PawnCnt[side][column (t)];
  1413.               ++PawnCnt[side][column (f)];
  1414.             }
  1415.           mtl[xside] += value[*tempb];
  1416.           if (*tempb == pawn)
  1417.             pmtl[xside] += valueP;
  1418. #if ttblsz
  1419.           UpdateHashbd (xside, *tempb, -1, t);
  1420. #endif /* ttblsz */
  1421.           Mvboard[t]--;
  1422.         }
  1423.       if (node->flags & epmask)
  1424.         EnPassant (xside, f, t, 2);
  1425.       else
  1426. #if ttblsz
  1427.         UpdateHashbd (side, board[f], f, t);
  1428. #else
  1429.       /* NOOP */;
  1430. #endif /* ttblsz */
  1431.       Mvboard[f]--;
  1432.       if (!(node->flags & capture) && (board[f] != pawn))
  1433.         rpthash[side][hashkey & 0xFF]--;
  1434.     }
  1435. }
  1436.  
  1437.  
  1438. void
  1439. InitializeStats (void)
  1440.  
  1441. /*
  1442.   Scan thru the board seeing what's on each square. If a piece is found,
  1443.   update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1444.   determine the material for each side and set the hashkey and hashbd
  1445.   variables to represent the current board position. Array
  1446.   PieceList[side][indx] contains the location of all the pieces of either
  1447.   side. Array Pindex[sq] contains the indx into PieceList for a given
  1448.   square.
  1449. */
  1450.  
  1451. {
  1452.   short i, sq;
  1453.   
  1454.   epsquare = -1;
  1455.   for (i = 0; i < 8; i++)
  1456.     PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1457.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1458.   PieceCnt[white] = PieceCnt[black] = 0;
  1459. #if ttblsz
  1460.   hashbd = hashkey = 0;
  1461. #endif /* ttblsz */
  1462.   for (sq = 0; sq < 64; sq++)
  1463.     if (color[sq] != neutral)
  1464.       {
  1465.         mtl[color[sq]] += value[board[sq]];
  1466.         if (board[sq] == pawn)
  1467.           {
  1468.             pmtl[color[sq]] += valueP;
  1469.             ++PawnCnt[color[sq]][column (sq)];
  1470.           }
  1471.         if (board[sq] == king)
  1472.           Pindex[sq] = 0;
  1473.         else
  1474.           Pindex[sq] = ++PieceCnt[color[sq]];
  1475.         PieceList[color[sq]][Pindex[sq]] = sq;
  1476. #if ttblsz
  1477.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  1478.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  1479. #endif /* ttblsz */
  1480.       }
  1481. }
  1482.  
  1483.  
  1484. int
  1485. SqAtakd (short int sq, short int side)
  1486.  
  1487. /*
  1488.   See if any piece with color 'side' ataks sq.  First check pawns then Queen,
  1489.   Bishop, Rook and King and last Knight.
  1490. */
  1491.  
  1492. {
  1493.   register short u;
  1494.   unsigned char far *ppos, far *pdir;
  1495.   short xside;
  1496.  
  1497.   xside = otherside[side];
  1498.   pdir = nextdir[ptype[xside][pawn]][sq];
  1499.   u = pdir[sq];         /* follow captures thread */
  1500.   if (u != sq)
  1501.     {
  1502.       if (board[u] == pawn && color[u] == side)
  1503.         return (true);
  1504.       u = pdir[u];
  1505.       if (u != sq && board[u] == pawn && color[u] == side)
  1506.         return (true);
  1507.     }
  1508.   /* king capture */
  1509.   if (distance (sq, PieceList[side][0]) == 1)
  1510.     return (true);
  1511.   /* try a queen bishop capture */
  1512.   ppos = nextpos[bishop][sq];
  1513.   pdir = nextdir[bishop][sq];
  1514.   u = ppos[sq];
  1515.   do
  1516.     {
  1517.       if (color[u] == neutral)
  1518.         u = ppos[u];
  1519.       else
  1520.         {
  1521.           if (color[u] == side &&
  1522.               (board[u] == queen || board[u] == bishop))
  1523.             return (true);
  1524.           u = pdir[u];
  1525.         }
  1526.   } while (u != sq);
  1527.   /* try a queen rook capture */
  1528.   ppos = nextpos[rook][sq];
  1529.   pdir = nextdir[rook][sq];
  1530.   u = ppos[sq];
  1531.   do
  1532.     {
  1533.       if (color[u] == neutral)
  1534.         u = ppos[u];
  1535.       else
  1536.         {
  1537.           if (color[u] == side &&
  1538.               (board[u] == queen || board[u] == rook))
  1539.             return (true);
  1540.           u = pdir[u];
  1541.         }
  1542.   } while (u != sq);
  1543.   /* try a knight capture */
  1544.   pdir = nextdir[knight][sq];
  1545.   u = pdir[sq];
  1546.   do
  1547.     {
  1548.       if (color[u] == side && board[u] == knight)
  1549.         return (true);
  1550.       u = pdir[u];
  1551.   } while (u != sq);
  1552.   return (false);
  1553. }
  1554.  
  1555. void
  1556. ataks (short int side, short int *a)
  1557.  
  1558. /*
  1559.   Fill array atak[][] with info about ataks to a square.  Bits 8-15 are set
  1560.   if the piece (king..pawn) ataks the square.  Bits 0-7 contain a count of
  1561.   total ataks to the square.
  1562. */
  1563.  
  1564. {
  1565.   short u, c, sq;
  1566.   unsigned char far *ppos, far *pdir;
  1567.   short i, piece, *PL;
  1568.  
  1569.   memset ((char *) a, 0, 64 * sizeof (a[0]));
  1570.   PL = PieceList[side];
  1571.   for (i = PieceCnt[side]; i >= 0; i--)
  1572.     {
  1573.       sq = PL[i];
  1574.       piece = board[sq];
  1575.       c = control[piece];
  1576.       if (sweep[piece])
  1577.         {
  1578.           ppos = nextpos[piece][sq];
  1579.           pdir = nextdir[piece][sq];
  1580.           u = ppos[sq];
  1581.           do
  1582.             {
  1583.               a[u] = ++a[u] | c;
  1584.               u = (color[u] == neutral) ? ppos[u] : pdir[u];
  1585.           } while (u != sq);
  1586.         }
  1587.       else
  1588.         {
  1589.           pdir = nextdir[ptype[side][piece]][sq];
  1590.           u = pdir[sq]; /* follow captures thread for pawns */
  1591.           do
  1592.             {
  1593.               a[u] = ++a[u] | c;
  1594.               u = pdir[u];
  1595.           } while (u != sq);
  1596.         }
  1597.     }
  1598. }
  1599. 
  1600.