home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / gnuchess.zip / GNUCHESS.C2 < prev    next >
Text File  |  1988-10-23  |  25KB  |  876 lines

  1. InitializeStats()
  2. {
  3. register short i,loc;
  4.   epsquare = -1;
  5.   for (i = 0; i < 8; i++)
  6.     PawnCnt[white][i] = PawnCnt[black][i] = 0;
  7.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  8.   PieceCnt[white] = PieceCnt[black] = 0;
  9.   hashbd = hashkey = 0;
  10.   for (loc = 0; loc < 64; loc++)
  11.     if (color[loc] != neutral)
  12.       {
  13.         mtl[color[loc]] += value[board[loc]];
  14.         if (board[loc] == pawn)
  15.           {
  16.             pmtl[color[loc]] += valueP;
  17.             ++PawnCnt[color[loc]][col[loc]];
  18.           }
  19.         if (board[loc] == king) Pindex[loc] = 0;
  20.           else Pindex[loc] = ++PieceCnt[color[loc]];
  21.         PieceList[color[loc]][Pindex[loc]] = loc;
  22.         hashbd ^= hashcode[color[loc]][board[loc]][loc].bd;
  23.         hashkey ^= hashcode[color[loc]][board[loc]][loc].key;
  24.       }
  25. }
  26.  
  27.  
  28. sort(p1,p2)
  29. short p1,p2;
  30. {
  31. register short p,p0,s;
  32. struct leaf temp;
  33.  
  34.   s = 32000;
  35.   while (p1 < p2)
  36.     if (Tree[p1].score >= s) p1++;
  37.     else
  38.       {
  39.         s = Tree[p1].score; p0 = p1;
  40.         for (p = p1+1; p <= p2; p++)
  41.           if (Tree[p].score > s)
  42.             {
  43.               s = Tree[p].score; p0 = p;
  44.             }
  45.         if (p0 != p1)
  46.           {
  47.             temp = Tree[p1]; Tree[p1] = Tree[p0]; Tree[p0] = temp;
  48.           }
  49.         p1++;
  50.       }
  51. }
  52.  
  53.  
  54. repetition(cnt)
  55. short *cnt;
  56.  
  57. /*
  58.     Check for draw by threefold repetition.
  59. */
  60.  
  61. {
  62. register short i,f,t;
  63. short c,b[64];
  64. unsigned short m;
  65.   *cnt = c = 0;
  66.   for (i = 0; i < 64; b[i++] = 0);
  67. /*
  68.   bzero((char *)b,sizeof(b));
  69.   memset((char *)b,0,64*sizeof(short));
  70. */
  71.   for (i = GameCnt; i > Game50; i--)
  72.     {
  73.       m = GameList[i].gmove; f = m>>8; t = m & 0xFF;
  74.       if (++b[f] == 0) c--; else c++;
  75.       if (--b[t] == 0) c--; else c++;
  76.       if (c == 0) (*cnt)++;
  77.     }
  78. }
  79.  
  80.  
  81. int SqAtakd(sq,side)
  82. short sq,side;
  83.  
  84. /*
  85.   Generate moves from 'sq' for each piece and see if the appropriate
  86.   piece with color 'side' is encountered.
  87. */
  88.  
  89. {
  90. register short i,u,m,d;
  91. short m0;
  92.  
  93.   m0 = map[sq];
  94.   
  95.   if (HasPawn[side])
  96.     {
  97.       d = Dpwn[otherside[side]];
  98.       for (i = d; i <= d+1; i++)
  99.         if ((u = unmap[m0+Dir[i]]) >= 0)
  100.           if (board[u] == pawn && color[u] == side) return(true);
  101.     }
  102.       
  103.   if (HasKnight[side])
  104.     for (i = 8; i <= 15; i++)
  105.       if ((u = unmap[m0+Dir[i]]) >= 0)
  106.         if (board[u] == knight && color[u] == side) return(true);
  107.       
  108.   if (HasRook[side] || HasQueen[side])
  109.     for (i = 0; i <= 3; i++)
  110.       {
  111.         d = Dir[i]; m = m0+d; u = unmap[m];
  112.         while (u >= 0)
  113.           if (color[u] == neutral)
  114.             {
  115.               m += d; u = unmap[m];
  116.             }
  117.           else if (color[u] == side && sweep1[board[u]]) return(true);
  118.           else break;
  119.       }
  120.     
  121.   if (HasBishop[side] || HasQueen[side])
  122.     for (i = 4; i <= 7; i++)
  123.       {
  124.         d = Dir[i]; m = m0+d; u = unmap[m];
  125.         while (u >= 0)
  126.           if (color[u] == neutral)
  127.             {
  128.               m += d; u = unmap[m];
  129.             }
  130.           else if (color[u] == side && sweep2[board[u]]) return(true);
  131.           else break;
  132.       }
  133.     
  134.   if (distance(sq,PieceList[side][0]) == 1) return(true);
  135.     
  136.   return(false);
  137. }
  138.  
  139.  
  140. ataks(side,a)
  141. short side,a[];
  142.  
  143. /*
  144.     Fill array atak[][] with info about ataks to a square.  Bits 8-15
  145.     are set if the piece (king..pawn) ataks the square. Bits 0-7
  146.     contain a count of total ataks to the square.
  147. */
  148.  
  149. {
  150. register short u,m,d,c;
  151. short j,piece,i,m0,loc;
  152.  
  153.   for (u = 0; u < 64; a[u++] = 0);
  154. /*
  155.   memset((char *)a,0,64*sizeof(short));
  156.   bzero((char *)a,sizeof(a));
  157. */
  158.   Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
  159.   for (i = 0; i <= PieceCnt[side]; i++)
  160.     {
  161.       loc = PieceList[side][i];
  162.       piece = board[loc]; m0 = map[loc]; c = control[piece];
  163.       if (sweep[piece])
  164.         for (j = Dstart[piece]; j <= Dstop[piece]; j++)
  165.           {
  166.             d = Dir[j]; m = m0+d; u = unmap[m];
  167.             while (u >= 0)
  168.               {
  169.                 a[u] = ++a[u] | c;
  170.                 if (color[u] == neutral)
  171.                   {
  172.                     m += d; u = unmap[m];
  173.                   }
  174.                 else break;
  175.               }
  176.           }
  177.       else
  178.         for (j = Dstart[piece]; j <= Dstop[piece]; j++)
  179.           if ((u = unmap[m0+Dir[j]]) >= 0)
  180.             a[u] = ++a[u] | c;
  181.     }
  182. }
  183.  
  184.   
  185. int castle(side,kf,kt,iop)
  186. short side,kf,kt,iop;
  187. {
  188. short i,rf,rt,c1,c2,t0,xside;
  189.  
  190.   xside = otherside[side];
  191.   if (kt > kf)
  192.     {
  193.       rf = kf+3; rt = kt-1; c1 = kf; c2 = rf;
  194.     }
  195.   else
  196.     {
  197.       rf = kf-4; rt = kt+1; c1 = rf; c2 = kf;
  198.     }
  199.   if (iop == 0)
  200.     {
  201.       if (board[kf] != king || board[rf] != rook || color[rf] != side)
  202.         return(false);
  203.       for (i = c1+1; i < c2; i++)
  204.         if (color[i] != neutral) return(false);
  205.       for (i = c1; i <= c2; i++)
  206.         if (SqAtakd(i,xside)) return(false); 
  207.     }
  208.   else
  209.     {
  210.       if (iop == 1) castld[side] = true; else castld[side] = false;
  211.       if (iop == 2)
  212.         {
  213.           t0 = kt; kt = kf; kf = t0;
  214.           t0 = rt; rt = rf; rf = t0;
  215.         }
  216.       board[kt] = king; color[kt] = side; Pindex[kt] = 0;
  217.       board[kf] = no_piece; color[kf] = neutral;
  218.       board[rt] = rook; color[rt] = side; Pindex[rt] = Pindex[rf];
  219.       board[rf] = no_piece; color[rf] = neutral;
  220.       PieceList[side][Pindex[kt]] = kt;
  221.       PieceList[side][Pindex[rt]] = rt;
  222.       UpdateHashbd(side,king,kf,kt);
  223.       UpdateHashbd(side,rook,rf,rt);
  224.     }
  225.   return(true);
  226. }
  227.  
  228.  
  229. en_passant(xside,f,t,iop)
  230. short xside,f,t,iop;
  231. {
  232. short l;
  233.   if (t > f) l = t-8; else l = t+8;
  234.   if (iop == 1)
  235.     {
  236.       board[l] = no_piece; color[l] = neutral;
  237.     }
  238.   else 
  239.     {
  240.       board[l] = pawn; color[l] = xside;
  241.     }
  242.   InitializeStats();
  243. }
  244.  
  245.  
  246. LinkMove(ply,f,t,xside)
  247. short ply,f,t,xside;
  248.  
  249. /*
  250.     Add a move to the tree.  Assign a bonus to order the moves
  251.     as follows:
  252.       1. Principle variation
  253.       2. Capture of last moved piece
  254.       3. Other captures (major pieces first)
  255.       4. Killer moves
  256.       5. "history" killers    
  257. */
  258.  
  259. {
  260. register short s;
  261. register unsigned short mv;
  262. struct leaf *node;
  263.  
  264.   node = &Tree[TrPnt[ply+1]];
  265.   ++TrPnt[ply+1];
  266.   node->flags = node->reply = 0;
  267.   node->f = f; node->t = t; mv = (f<<8) + t;
  268.   s = 0;
  269.   if (mv == PV || mv == Swag0) s = 2000;
  270.   else if (mv == Swag1) s = 80;
  271.   else if (mv == Swag2) s = 70;
  272.   else if (mv == Swag3) s = 60;
  273.   else if (mv == Swag4) s = 40;
  274.   else if (mv == Swag5) s = 30;
  275.   if (color[t] != neutral)
  276.     {
  277.       node->flags |= capture;
  278.       if (t == TOsquare) s += 800;
  279.       s += value[board[t]] - board[f];
  280.     }
  281.   if (board[f] == pawn)
  282.     {
  283.       if (row[t] == 0 || row[t] == 7)
  284.         {
  285.           node->flags |= promote;
  286.           s += 500;
  287.         }
  288.       else if (row[t] == 1 || row[t] == 6)
  289.         {
  290.           node->flags |= pwnthrt;
  291.           s += 500;
  292.         }
  293.       else if (t == epsquare) node->flags |= epmask;
  294.     }
  295.   if (InChk)
  296.     {
  297.       if (board[f] == king)
  298.         if (SqAtakd(t,xside)) s -= 200; else s += 400;
  299.       if (mv == Qkillr[ply]) s += 200;
  300.     }
  301.   s += history[otherside[xside]-1][f][t];
  302.   node->score = s-20000;
  303. }
  304.  
  305.  
  306. GenMoves(ply,loc,side,xside)
  307. short ply,loc,side,xside;
  308.  
  309. /*
  310.      Generate moves for a piece. The from square is mapped onto a 12 by 
  311.      12 board and offsets (taken from array Dir[]) are added to the 
  312.      mapped location. Array unmap[] maps the move back onto array 
  313.      board[] (yielding a value of -1 if the to square is off the board). 
  314.      This process is repeated for bishops, rooks, and queens until a 
  315.      piece is encountered or the the move falls off the board. Legal 
  316.      moves are then linked into the tree. 
  317. */
  318.     
  319. {
  320. register short m,u,d;
  321. short i,m0,piece; 
  322.  
  323.   piece = board[loc]; m0 = map[loc];
  324.   if (sweep[piece])
  325.     for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  326.       {
  327.         d = Dir[i]; m = m0+d; u = unmap[m];
  328.         while (u >= 0)
  329.           if (color[u] == neutral)
  330.             {
  331.               LinkMove(ply,loc,u,xside);
  332.               m += d; u = unmap[m];
  333.             }
  334.           else if (color[u] == xside)
  335.             {
  336.               LinkMove(ply,loc,u,xside);
  337.               break;
  338.             }
  339.           else break;
  340.       }
  341.   else if (piece == pawn)
  342.     {
  343.       if (side == white && color[loc+8] == neutral)
  344.         {
  345.           LinkMove(ply,loc,loc+8,xside);
  346.           if (row[loc] == 1)
  347.             if (color[loc+16] == neutral)
  348.               LinkMove(ply,loc,loc+16,xside);
  349.         }
  350.       else if (side == black && color[loc-8] == neutral)
  351.         {
  352.           LinkMove(ply,loc,loc-8,xside);
  353.           if (row[loc] == 6)
  354.             if (color[loc-16] == neutral)
  355.               LinkMove(ply,loc,loc-16,xside);
  356.         }
  357.       for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  358.         if ((u = unmap[m0+Dir[i]]) >= 0)
  359.           if (color[u] == xside || u == epsquare)
  360.             LinkMove(ply,loc,u,xside);
  361.     }
  362.   else
  363.     {
  364.       for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  365.         if ((u = unmap[m0+Dir[i]]) >= 0)
  366.           if (color[u] != side)
  367.             LinkMove(ply,loc,u,xside);
  368.     }
  369. }
  370.  
  371.  
  372. MoveList(side,ply)
  373. short side,ply;
  374.  
  375. /*
  376.     Fill the array Tree[] with all available moves for side to
  377.     play. Array TrPnt[ply] contains the index into Tree[]
  378.     of the first move at a ply.
  379. */
  380.     
  381. {
  382. register short i;
  383. short xside,f;
  384.  
  385.   xside = otherside[side];
  386.   Swag0 = killr0[ply]; Swag1 = killr1[ply]; Swag2 = killr2[ply];
  387.   Swag3 = killr3[ply]; Swag4 = Swag5 = 0;
  388.   if (ply > 2)
  389.     {
  390.       Swag4 = killr1[ply-2];
  391.       Swag5 = killr3[ply-2];
  392.     }
  393.   TrPnt[ply+1] = TrPnt[ply];
  394.   Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
  395.   for (i = PieceCnt[side]; i >= 0; i--)
  396.     GenMoves(ply,PieceList[side][i],side,xside);
  397.   if (kingmoved[side] == 0)
  398.     {
  399.       f = PieceList[side][0];
  400.       if (castle(side,f,f+2,0))
  401.         {
  402.           LinkMove(ply,f,f+2,xside);
  403.           Tree[TrPnt[ply+1]-1].flags |= cstlmask;
  404.         }
  405.       if (castle(side,f,f-2,0))
  406.         {
  407.           LinkMove(ply,f,f-2,xside);
  408.           Tree[TrPnt[ply+1]-1].flags |= cstlmask;
  409.         }
  410.     }
  411.   sort(TrPnt[ply],TrPnt[ply+1]-1);
  412. }
  413.  
  414.  
  415. #define LinkCapture\
  416. {\
  417.   node = &Tree[TrPnt[ply+1]];\
  418.   ++TrPnt[ply+1];\
  419.   node->f = loc; node->t = u;\
  420.   node->reply = 0;\
  421.   node->flags = capture;\
  422.   node->score = value[board[u]] + svalue[board[u]] - piece;\
  423.   if (piece == pawn && (u < 8 || u > 55))\
  424.     {\
  425.       node->flags |= promote;\
  426.       node->score = valueQ;\
  427.     }\
  428. }
  429.  
  430.  
  431. CaptureList(side,xside,ply)
  432. short side,xside,ply;
  433.  
  434. /*
  435.     Generate a list of captures similiarly to GenMoves.
  436. */
  437.  
  438. {
  439. register short m,u,d;
  440. short loc,i,j,m0,piece;
  441. struct leaf *node;
  442.  
  443.   TrPnt[ply+1] = TrPnt[ply];
  444.   Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
  445.   for (i = 0; i <= PieceCnt[side]; i++)
  446.     { 
  447.       loc = PieceList[side][i];
  448.       piece = board[loc]; m0 = map[loc];
  449.       if (sweep[piece])
  450.         for (j = Dstart[piece]; j <= Dstop[piece]; j++)
  451.           {
  452.             d = Dir[j]; m = m0+d; u = unmap[m];
  453.             while (u >= 0)
  454.               if (color[u] == neutral)
  455.                 {
  456.                   m += d; u = unmap[m];
  457.                 }
  458.               else
  459.                 {
  460.                   if (color[u] == xside) LinkCapture;
  461.                   break;
  462.                 }
  463.           }
  464.       else
  465.         {
  466.           for (j = Dstart[piece]; j <= Dstop[piece]; j++)
  467.             if ((u = unmap[m0+Dir[j]]) >= 0)
  468.               if (color[u] == xside) LinkCapture;
  469.           if (piece == pawn && row[loc] == rank7[side])
  470.             {
  471.               if (side == white) u = loc+8; else u = loc-8;
  472.               if (color[u] == neutral) LinkCapture;
  473.             }
  474.         }
  475.    }
  476.   sort(TrPnt[ply],TrPnt[ply+1]-1);
  477. }
  478.  
  479.  
  480. MakeMove(side,node,tempb,tempc,temps)
  481. short side,*tempc,*tempb,*temps;
  482. struct leaf *node;
  483.  
  484. /*
  485.     Update Arrays board[], color[], and Pindex[] to reflect the new
  486.     board position obtained after making the move pointed to by
  487.     node.  Also update miscellaneous stuff that changes when a move
  488.     is made.
  489. */
  490.     
  491. {
  492. register short f,t;
  493. short xside;
  494.  
  495.   xside = otherside[side];
  496.   f = node->f; t = node->t; epsquare = -1;
  497.   TOsquare = t; cptrval = 0;
  498.   GameList[++GameCnt].gmove = (f<<8) + t;
  499.   if (node->flags & cstlmask)
  500.     {
  501.       GameList[GameCnt].piece = no_piece;
  502.       GameList[GameCnt].color = side;
  503.       castle(side,f,t,1);
  504.     }
  505.   else
  506.     {
  507.       *tempc = color[t]; *tempb = board[t]; *temps = svalue[t];
  508.       GameList[GameCnt].piece = *tempb;
  509.       GameList[GameCnt].color = *tempc;
  510.       if (*tempc != neutral)
  511.         {
  512.           UpdatePieceList(*tempc,t,1);
  513.           if (*tempb == pawn) --PawnCnt[*tempc][col[t]];
  514.           if (board[f] == pawn)
  515.             {
  516.               --PawnCnt[side][col[f]];
  517.               ++PawnCnt[side][col[t]];
  518.             }
  519.           mtl[xside] -= value[*tempb];
  520.           if (*tempb == pawn) pmtl[xside] -= valueP;
  521.           UpdateHashbd(xside,*tempb,-1,t);
  522.           cptrval = *temps;
  523.         }
  524.       color[t] = color[f]; board[t] = board[f]; svalue[t] = svalue[f];
  525.       Pindex[t] = Pindex[f]; PieceList[side][Pindex[t]] = t;
  526.       color[f] = neutral; board[f] = no_piece;
  527.       if (board[t] == pawn)
  528.         if (t-f == 16) epsquare = f+8;
  529.         else if (f-t == 16) epsquare = f-8;
  530.       if (node->flags & promote)
  531.         {
  532.           board[t] = queen;
  533.           --PawnCnt[side][col[t]];
  534.           mtl[side] += valueQ - valueP;
  535.           pmtl[side] -= valueP;
  536.           HasQueen[side] = true;
  537.           cptrval -= svalue[f];
  538.           UpdateHashbd(side,pawn,f,-1);
  539.           UpdateHashbd(side,queen,f,-1);
  540.         } 
  541.       if (board[t] == king) ++kingmoved[side];
  542.       if (node->flags & epmask) en_passant(xside,f,t,1);
  543.       else UpdateHashbd(side,board[t],f,t);
  544.     }
  545. }
  546.  
  547.  
  548. UnmakeMove(side,node,tempb,tempc,temps)
  549. short side,*tempc,*tempb,*temps;
  550. struct leaf *node;
  551.  
  552. /*
  553.     Take back the move pointed to by node.
  554. */
  555.  
  556. {
  557. register short f,t;
  558. short xside;
  559.  
  560.   xside = otherside[side];
  561.   f = node->f; t = node->t; epsquare = -1;
  562.   GameCnt--;
  563.   if (node->flags & cstlmask) castle(side,f,t,2);
  564.   else
  565.     {
  566.       color[f] = color[t]; board[f] = board[t]; svalue[f] = svalue[t];
  567.       Pindex[f] = Pindex[t]; PieceList[side][Pindex[f]] = f;
  568.       color[t] = *tempc; board[t] = *tempb; svalue[t] = *temps;
  569.       if (node->flags & promote)
  570.         {
  571.           board[f] = pawn;
  572.           ++PawnCnt[side][col[t]];
  573.           mtl[side] += valueP - valueQ;
  574.           pmtl[side] += valueP;
  575.           UpdateHashbd(side,queen,-1,t);
  576.           UpdateHashbd(side,pawn,-1,t);
  577.         } 
  578.       if (*tempc != neutral)
  579.         {
  580.           UpdatePieceList(*tempc,t,2);
  581.           if (*tempb == pawn) ++PawnCnt[*tempc][col[t]];
  582.           if (board[f] == pawn)
  583.             {
  584.               --PawnCnt[side][col[t]];
  585.               ++PawnCnt[side][col[f]];
  586.             }
  587.           mtl[xside] += value[*tempb];
  588.           if (*tempb == pawn) pmtl[xside] += valueP;
  589.           UpdateHashbd(xside,*tempb,-1,t);
  590.         }
  591.       if (board[f] == king) --kingmoved[side];
  592.       if (node->flags & epmask) en_passant(xside,f,t,2);
  593.       else UpdateHashbd(side,board[f],f,t);
  594.     }
  595. }
  596.  
  597.  
  598. distance(a,b)
  599. short a,b;
  600. {
  601. short d1,d2;
  602.  
  603.   d1 = absv(col[a]-col[b]);
  604.   d2 = absv(row[a]-row[b]);
  605.   if (d1 > d2) return(d1); else return(d2);
  606. }
  607.  
  608.  
  609. BlendBoard(a,b,c)
  610. short a[64],b[64],c[64];
  611. {
  612. register int sq;
  613.   for (sq = 0; sq < 64; sq++)
  614.     c[sq] = (a[sq]*(10-stage) + b[sq]*stage) / 10;
  615. }
  616.  
  617.  
  618. CopyBoard(a,b)
  619. short a[64],b[64];
  620. {
  621. register int sq;
  622.   for (sq = 0; sq < 64; sq++)
  623.     b[sq] = a[sq];
  624. }
  625.  
  626.  
  627. UpdateWeights()
  628. {
  629. short tmtl;
  630.  
  631.   if (mtl[white] != Zwmtl || mtl[black] != Zbmtl)
  632.     {
  633.       Zwmtl = mtl[white]; Zbmtl = mtl[black];
  634.       emtl[white] = Zwmtl - pmtl[white] - valueK;
  635.       emtl[black] = Zbmtl - pmtl[black] - valueK;
  636.       tmtl = emtl[white] + emtl[black];
  637.       if (tmtl > 5700) stage = 0;
  638.       else if (tmtl < 1300) stage = 10;
  639.       else stage = (5700-tmtl) / 440;
  640.       
  641.       PEDRNK2B = -15;         /* centre pawn on 2nd rank & blocked */
  642.       PBKWRD = -6;            /* backward pawns */
  643.       PWEAKA  = -3;           /* each attack to weak pawn */
  644.       PWEAKH  = -3;           /* weak pawn on half open file */
  645.       PAWNSHIELD = 10-stage;  /* pawn near friendly king */
  646.       PADVNCM =  (10+stage)/2;    /* advanced pawn multiplier */
  647.       
  648.       KNIGHTPOST = (stage+2)/3;   /* knight near enemy pieces */
  649.       KNIGHTSTRONG = (stage+6)/2; /* occupies pawn hole */
  650.       
  651.       BISHOPSTRONG = (stage+6)/2; /* occupies pawn hole */
  652.       
  653.       RHOPN    = 10;          /* rook on half open file */
  654.       RHOPNX   = 4;
  655.       
  656.       XRAY     = 8;           /* Xray attack on major piece */
  657.       
  658.       KHOPN    = (3*stage-30) / 2; /* king on half open file */
  659.       KHOPNX   = KHOPN / 2;
  660.       KCASTLD  = 10 / (stage+1);   /* king castled */
  661.       KMOVD    = -40 / (stage+1);  /* king moved before castling */
  662.       KATAK    = 5;                /* B,R attacks near enemy king */
  663.       if (stage < 8) KSFTY = 8-stage; else KSFTY = 0;
  664.       
  665.       ATAKD    = -6;          /* defender > attacker */
  666.       HUNGP    = -8;          /* each hung piece */
  667.       HUNGX    = -10;         /* extra for >1 hung piece */
  668.     }
  669. }
  670.  
  671.  
  672. ExaminePosition()
  673. /*
  674.   This is done one time before the search is started.
  675.   Set up arrays Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used
  676.   in the SqValue() function to determine the positional value of each
  677.   piece.
  678. */
  679. {
  680. register short i,sq;
  681. short r,wpadv,bpadv,z,side,pp,j;
  682. long stage2,tpmtl,Pd,val;
  683.  
  684.   wking = PieceList[white][0]; bking = PieceList[black][0];
  685.   ataks(white,atak[white]); ataks(black,atak[black]);
  686.   Zwmtl = Zbmtl = 0;
  687.   UpdateWeights();
  688.   stage2 = stage*stage; tpmtl = pmtl[white] + pmtl[black];
  689.   HasPawn[white] = HasPawn[black] = false;
  690.   HasKnight[white] = HasKnight[black] = false;
  691.   HasBishop[white] = HasBishop[black] = false;
  692.   HasRook[white] = HasRook[black] = false;
  693.   HasQueen[white] = HasQueen[black] = false;
  694.   for (side = white; side <= black; side++)
  695.     for (i = 0; i <= PieceCnt[side]; i++)
  696.       switch (board[PieceList[side][i]])
  697.         {
  698.           case pawn : HasPawn[side] = true; break;
  699.           case knight : HasKnight[side] = true; break;
  700.           case bishop : HasBishop[side] = true; break;
  701.           case rook : HasRook[side] = true; break;
  702.           case queen : HasQueen[side] = true; break;
  703.         }
  704.   if (!Developed[white])
  705.     Developed[white] = (board[1] != knight && board[2] != bishop &&
  706.                         board[5] != bishop && board[6] != knight);
  707.   if (!Developed[black])
  708.     Developed[black] = (board[57] != knight && board[58] != bishop &&
  709.                         board[61] != bishop && board[62] != knight);
  710.     
  711.   for (sq = 0; sq < 64; sq++)
  712.     {
  713.       WeakSq[white][sq] = WeakSq[black][sq] = true;
  714.       for (i = sq; i >= 0; i -= 8)
  715.         if (atak[white][i] >= ctlP) WeakSq[white][sq] = false;
  716.       for (i = sq; i < 64; i += 8)
  717.         if (atak[black][i] >= ctlP) WeakSq[black][sq] = false;
  718.       Kfield[white][sq] = Kfield[black][sq] = 0;
  719.     }
  720.   
  721.   CopyBoard(pknight,Mknight[white]);
  722.   CopyBoard(pknight,Mknight[black]);
  723.   CopyBoard(pbishop,Mbishop[white]);
  724.   CopyBoard(pbishop,Mbishop[black]);
  725.   BlendBoard(KingOpening,KingEnding,Mking[white]);
  726.   BlendBoard(KingOpening,KingEnding,Mking[black]);
  727.   
  728.   if (!Developed[white])
  729.     {
  730.        Mknight[white][1] -= 5;
  731.        Mbishop[white][2] -= 5;
  732.        Mbishop[white][5] -= 5;
  733.        Mknight[white][6] -= 5;
  734.     }
  735.   if (!Developed[black])
  736.     {
  737.        Mknight[black][57] -= 5;
  738.        Mbishop[black][58] -= 5;
  739.        Mbishop[black][61] -= 5;
  740.        Mknight[black][62] -= 5;
  741.     }
  742.     
  743.   for (sq = 0; sq < 64; sq++)
  744.     {
  745.       wpadv = bpadv = PADVNCM;
  746.       Mwpawn[sq] = (wpadv*PawnAdvance[sq]) / 10;
  747.       Mbpawn[sq] = (bpadv*PawnAdvance[63-sq]) / 10;
  748.       if (distance(sq,wking) < 3 && (col[sq] < 3 || col[sq] > 4))
  749.         Mwpawn[sq] += PAWNSHIELD;
  750.       if (distance(sq,bking) < 3 && (col[sq] < 3 || col[sq] > 4))
  751.         Mbpawn[sq] += PAWNSHIELD;
  752.         
  753.       Mknight[white][sq] += 5 - distance(sq,bking);
  754.       Mknight[white][sq] += 5 - distance(sq,wking);
  755.       Mknight[black][sq] += 5 - distance(sq,wking);
  756.       Mknight[black][sq] += 5 - distance(sq,bking);
  757.       Mbishop[white][sq] += stage;
  758.       Mbishop[black][sq] += stage;
  759.       for (i = 0; i <= PieceCnt[black]; i++)
  760.         if (distance(sq,PieceList[black][i]) < 3)
  761.           Mknight[white][sq] += KNIGHTPOST;
  762.       for (i = 0; i <= PieceCnt[white]; i++)
  763.         if (distance(sq,PieceList[white][i]) < 3)
  764.           Mknight[black][sq] += KNIGHTPOST;
  765.       if (WeakSq[black][sq]) Mknight[white][sq] += KNIGHTSTRONG;
  766.       if (WeakSq[white][sq]) Mknight[black][sq] += KNIGHTSTRONG;
  767.       if (WeakSq[black][sq]) Mbishop[white][sq] += BISHOPSTRONG;
  768.       if (WeakSq[white][sq]) Mbishop[black][sq] += BISHOPSTRONG;
  769.       
  770.       Pd = 0;
  771.       for (i = 0; i < 64; i++)
  772.         if (board[i] == pawn)
  773.           {
  774.             if (color[i] == white)
  775.               {
  776.                 r = row[i]+3; pp = true;
  777.                 if (row[i] == 6) z = i+8; else z = i+16;
  778.                 for (j = i+8; j < 64; j += 8)
  779.                   if (!WeakSq[black][j]) pp = false;
  780.               }
  781.             else
  782.               {
  783.                 r = 10-row[i]; pp = true;
  784.                 if (row[i] == 1) z = i-8; else z = i-16;
  785.                 for (j = i-8; j >= 0; j -= 8)
  786.                   if (!WeakSq[white][j]) pp = false;
  787.               }
  788.             if (pp) r *= 4;
  789.             Pd += r*distance(sq,z);
  790.           }
  791.       if (tpmtl > 0)
  792.         {
  793.           val = (Pd*stage2) / (2*tpmtl);
  794.           Mking[white][sq] -= (short)val;
  795.           Mking[black][sq] -= (short)val;
  796.         }
  797.  
  798.       if (distance(sq,wking) == 1) Kfield[black][sq] += KATAK;
  799.       if (distance(sq,bking) == 1) Kfield[white][sq] += KATAK;
  800.     }
  801. }
  802.  
  803.  
  804. int trapped(loc,piece)
  805. short loc,piece;
  806. /*
  807.   See if the attacked piece has unattacked squares to move to.
  808.   If it is trapped, increment the hung[] array so that the search
  809.   will be extended.
  810. */
  811. {
  812. register short u,m,d;
  813. short i,m0;
  814.  
  815.   m0 = map[loc];
  816.   if (sweep[piece])
  817.     for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  818.       {
  819.         d = Dir[i]; m = m0+d; u = unmap[m];
  820.         while (u >= 0)
  821.           if (color[u] == c1) break;
  822.           else if (atak[c2][u] == 0 || board[u] >= piece) return(false);
  823.           else if (color[u] == c2) break;
  824.           else
  825.             {
  826.               m += d; u = unmap[m];
  827.             }
  828.       }
  829.   else if (piece == pawn)
  830.     {
  831.        if (c1 == white) u = loc+8; else u = loc-8;
  832.        if (color[u] == neutral && atak[c1][u] >= atak[c2][u])
  833.                best = node->score; pbst = pnt;
  834.           if (best > alpha) alpha = best;
  835.           for (j = ply+1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
  836.           bstline[j] = 0;
  837.           bstline[ply] = (node->f<<8) + node->t;
  838.           if (ply == 1)
  839.             {
  840.               if (post) post_move(node);
  841.               if (best == alpha)
  842.                 {
  843.                   tmp = Tree[pnt];
  844.                   for (j = pnt-1; j >= 0; j--) Tree[j+1] = Tree[j];
  845.                   Tree[0] = tmp;
  846.                 }
  847.               if (Sdepth > 2)
  848.                 if (best > beta) ShowResults('+');
  849.                 else if (best < alpha) ShowResults('-');
  850.                 else ShowResults('&');
  851.             }
  852.         }
  853.       if (NodeCnt > ETnodes) ElapsedTime(0);
  854.     }
  855.   if (ply == 1) node = &Tree[0]; else node = &Tree[pbst];
  856.   mv = (node->f<<8) + node->t;
  857.   if (ply <= Sdepth && *rpt == 0 && !timeout && hashflag)
  858.     PutInTTable(side,best,xdepth,alpha,beta,bstline[ply+1]);
  859.   if (depth > 0)
  860.     if (history[side-1][node->f][node->t] < 180)
  861.       history[side-1][node->f][node->t] += depth;
  862.   if (node->t != (GameList[GameCnt].gmove & 0xFF))
  863.     if (best <= beta) killr3[ply] = mv;
  864.     else if (mv != killr1[ply])
  865.       {
  866.         killr2[ply] = killr1[ply];
  867.         killr1[ply] = mv;
  868.       }
  869.   if (in_check && best > -9000) Qkillr[ply] = mv;
  870.   if (best > 9000) killr0[ply] = mv; else killr0[ply] = 0;
  871.   if (timeout || (best < alpha && -Tscore[ply-1] < best))
  872.     best = -Tscore[ply-1];
  873.   return(best);
  874. }
  875.  
  876.