home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / Chess-9 / gnuchess.c < prev    next >
C/C++ Source or Header  |  1992-03-07  |  64KB  |  2,369 lines

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