home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 5 / ctrom5b.zip / ctrom5b / OS2 / SPEL / UCHESS / UCHESSRC / SEARCH.C < prev    next >
Text File  |  1994-10-29  |  55KB  |  1,989 lines

  1. // about splitting the search into a new thread, perhaps
  2. // the best place to check the msg queue is in UpdateClocks,
  3. // called from ElapsedTime, you would set a flag in here
  4. // before you call each ElapsedTime, telling the system
  5. // to check the msg queue in there for any new moves
  6.  
  7. //char strx[40];
  8. #define CLEARHISTBETWEENMOVES // old way to handle hist table
  9. /*
  10.  * search.c - C source for GNU CHESS
  11.  *
  12.  * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
  13.  * Foundation
  14.  *
  15.  * This file is part of GNU CHESS.
  16.  *
  17.  * GNU Chess is free software; you can redistribute it and/or modify it under
  18.  * the terms of the GNU General Public License as published by the Free
  19.  * Software Foundation; either version 2, or (at your option) any later
  20.  * version.
  21.  *
  22.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  23.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  24.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  25.  * details.
  26.  *
  27.  * You should have received a copy of the GNU General Public License along with
  28.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  29.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  30.  */
  31. #include "gnuchess.h"
  32.  
  33. //#define PTRHEIGHT 55
  34. //extern UWORD myPointer[];
  35. // extern struct Window __aligned *wG;
  36. extern int __aligned SupervisorMode;
  37. extern INTSIZE __aligned amigaboard[64],amigacolor[64];
  38.  
  39.  
  40. #define ZEROALLBETWEENPLY 1
  41.  
  42. #ifndef AMIGA
  43. extern ULONG Global_Message;
  44. extern HEV semhandle;
  45. //void SignalInputThread(unsigned long);
  46. // this routine has to signal the input thread
  47. // providing the long value in the global mailbox slot
  48. //void SignalInputThread(val)
  49. //ULONG val;
  50. //{
  51. // Global_Message = val;
  52. // DosPostEventSem(semhandle);
  53. //}
  54. #endif
  55.  
  56. #ifdef QUIETBACKGROUND
  57. short __aligned background = 0;
  58.  
  59. #endif /* QUIETBACKGROUND */
  60. static short int __aligned DepthBeyond;
  61. short __aligned Threat[MAXDEPTH];
  62. unsigned short int __aligned PrVar[MAXDEPTH];
  63. extern short int ISZERO;
  64. extern long EADD,EGET;
  65. extern char mvstr[8][8];
  66. extern short int recycle;
  67. extern int __aligned GetEntryDone;
  68. extern int trying_again;
  69. short int __aligned myflagdeepnull=0xff;
  70. int got_20000=0;
  71. short __aligned ThreatSave[MAXDEPTH]; /* tom@izf.tno.nl */
  72. extern short __aligned QueenCheck[MAXDEPTH]; /* tom@izf.tno.nl */
  73. #if defined NULLMOVE || defined DEEPNULL
  74. short int __aligned no_null;
  75. short int __aligned null;         /* Null-move already made or not */
  76. short int __aligned PVari;        /* Is this the PV */
  77. #endif
  78. #ifdef DEBUG40
  79. extern int whichway;
  80. #endif
  81. #ifdef DEBUG
  82. unsigned short __aligned DBLINE[MAXDEPTH];
  83. struct leaf __aligned *dbptr;
  84.  
  85. #endif
  86. short __aligned start_stage;
  87. short __aligned thrashing_tt; /* must we recycle slots at random. TomV */
  88. short int __aligned zwndw;
  89.  
  90. #include "ataks3.h"
  91.  
  92.  
  93. extern long OrigResponse;
  94. extern int global_tmp_score;
  95. extern int previous_score;
  96. short __aligned myflagpvs=true;
  97. int __aligned backsrchaborted=0;
  98. int __aligned Sdepth2=0;
  99. extern int MoveNowOK;
  100. //extern int procpri;
  101. //extern struct Process *myproc;
  102. //extern struct MsgPort *InThreadPort;
  103.  
  104. int __aligned RealThink=0;
  105.  
  106. #ifdef SPEED_PRECALC
  107. unsigned short __aligned PreCalcedHint;
  108. unsigned short __aligned PreCalcedMove;
  109. int DoPreCalc (unsigned INTSIZE *, INTSIZE);
  110. #endif
  111. int __aligned Castled[2]={0,0};
  112. int __aligned myEnPassant[2]={0,0};
  113.  
  114. #include "ttable.c"
  115.  
  116.  
  117. short int __inline repetition (void);
  118.  
  119.  
  120. #include "debug41.h"
  121. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  122.  
  123. //#define STRAIGHT4PL70 1 // for repetiton code
  124. #ifndef STRAIGHT4PL70
  125. // improved Kong Sian Repetition
  126.  
  127. short int __inline
  128. repetition ()
  129.  
  130. /*  Check for draw by threefold repetition.  */
  131.  
  132. {
  133.   register short i, cnt;
  134.  
  135.   cnt = 0;
  136.   /* try to avoid work */
  137.   if (GameCnt > Game50 + 3)
  138.     for (i = GameCnt; i >= Game50; i--)
  139.       if (hashbd == GameList[i].hashbd && hashkey == GameList[i].hashkey)
  140.     cnt++;
  141.  
  142.   return cnt;
  143. }
  144.  
  145. #else // straight 4pl70 repetition
  146. short int __inline
  147. repetition ()
  148.  
  149. /*  Check for draw by threefold repetition.  */
  150.  
  151. {
  152.   register SHORT i, c, cnt;
  153.   register SHORT m;
  154.   SHORT b[64];
  155.  
  156.   cnt = c = 0;
  157.   /* try to avoid work */
  158.   if (GameCnt > Game50 + 3)
  159.     {
  160.       ClearMem(b,sizeof(b));
  161.       for (i = GameCnt; i >= Game50; i--)
  162.     {
  163.       m = GameList[i].gmove;
  164.       /* does piece exist on diff board? */
  165.       if (b[m & 0x3f])
  166.         {
  167.           /* does diffs cancel out, piece back? */
  168.           if ((b[m >> 8] += b[m & 0x3f]) == 0)
  169.         --c;
  170.           b[m & 0x3f] = 0;
  171.         }
  172.       else
  173.         {
  174.           /* create diff */
  175.           ++c;
  176.           /* does diff cancel out another diff? */
  177.           if (!(b[m >> 8] -= (b[m & 0x3f] = board[m & 0x3f] +
  178.                   (color[m & 0x3f] << 8))))
  179.         --c;
  180.         }
  181.       /* if diff count is 0 we have a repetition */
  182.       if (c == 0)
  183.         if ((i ^ GameCnt) & 1)
  184.           cnt++;
  185.     }
  186.     }
  187.   return cnt;
  188. }
  189.  
  190. #endif // striaght 4pl70 repetition
  191.  
  192. int plyscore, globalscore;
  193. int
  194. pick (short int p1, short int p2)
  195.  
  196. /*
  197.  * Find the best move in the tree between indexes p1 and p2. Swap the best
  198.  * move into the p1 element.
  199.  *
  200.  */
  201. {
  202.   register struct leaf *p, *q, *r, *k;
  203.   register s0;
  204.   struct leaf temp;
  205.  
  206.   k = p = &Tree[p1];
  207.   q = &Tree[p2];
  208.   s0 = p->score;
  209.   for (r = p + 1; r <= q; r++)
  210.     if (r->score != 9999 && (r->score) > s0) // this is the PL70 way!
  211. //    if ((r->score) > s0) 
  212.       {
  213.     s0 = (r->score);
  214.     p = r;
  215.       }
  216.   if (p != k)
  217.     {
  218.       temp = *p;
  219.       *p = *k;
  220.       *k = temp;
  221.       return true;
  222.     }
  223.   return false;
  224. }
  225.  
  226. #ifdef DEBUG
  227. unsigned short trace[MAXDEPTH];
  228. char traceline[256];
  229. unsigned short tracelog[MAXDEPTH];
  230. int tracen = 0;
  231. int traceflag = 0;
  232. int traceply = 0;
  233. #endif
  234. int __aligned bookflag = false;
  235. int __aligned Jscore = 0;
  236.  
  237. static int __aligned TCcount, TCleft;
  238. void
  239. SelectMove (short int side, short int iop)
  240. /*
  241.  * Select a move by calling function search() at progressively deeper ply
  242.  * until time is up or a mate or draw is reached. An alpha-beta window of
  243.  * -Awindow to +Bwindow points is set around the score returned from the
  244.  * previous iteration. If Sdepth != 0 then the program has correctly
  245.  * predicted the opponents move and the search will start at a depth of
  246.  * Sdepth+1 rather than a depth of 1.
  247.  */
  248. {
  249.   static short int i, tempb, tempc, tempsf, tempst, xside, rpt;
  250.   static short int alpha, beta, score;
  251.   static struct GameRec *g;
  252.   int earlyflag;
  253.  
  254. #ifndef CLEARHISTBETWEENMOVES // old way to handle hist table
  255.   int cnt;
  256.   ULONG *tmphistptr;
  257. #endif
  258.  
  259.   //char mystr[32];               
  260.   short InChkDummy;
  261.   short start_score;
  262. #ifdef DEBUG
  263.  
  264. if(debuglevel & (512|1024)){
  265.     char b[32];
  266.     short c1,c2,r1,r2;
  267. tracen=0;
  268. traceflag = false;
  269. traceply = 0;
  270. tracelog[0]=0;
  271. while(true){
  272.     /*printf("debug?");
  273.     gets(b);*/
  274.     if(b[0] == 'p')traceply = atoi(&b[1]);
  275.     else
  276.     if(b[0] == '\0')break;
  277.     else{
  278.         c1 = b[0] - 'a';
  279.         r1 = b[1] - '1';
  280.         c2 = b[2] - 'a';
  281.         r2 = b[3] - '1';
  282.         trace[++tracen] = (locn (r1, c1) << 8) | locn (r2, c2);
  283.     }
  284.     if(tracen == 0 && traceply >0)traceflag = true;
  285.     }
  286.     
  287. }
  288. #endif
  289.  
  290. //  InitializeStats(); // MY FIX FOR UNDO PROBLEMS!!! TMP!!!
  291.  
  292. //if (!SupervisorMode)
  293. // SetPointer(wG,myPointer,PTRHEIGHT,0x10L,0L,0L);
  294. got_20000 = 0;
  295. if (iop != 2)
  296.  {
  297.   RealThink = 1;
  298.   if (!GetEntryDone)
  299.    {   // I guess for OS/2 here I would set an event
  300.        // semaphore for the get thread.
  301. #ifdef AMIGA    
  302.     Global_Message.myData = 1L;
  303.     Forbid();
  304.     PutMsg(InThreadPort,(struct Message *)&Global_Message);
  305.     Permit();
  306. #else
  307.    //SignalInputThread(1L);
  308. #endif
  309.     GetEntryDone = 1;
  310.    }
  311.  }
  312. else
  313.  RealThink = 0;
  314. //start_again:
  315.   flag.timeout = false;
  316.   flag.back = flag.musttimeout = false;
  317.   INCscore = 0; // new from 4pl70, do I want this?
  318.   xside = side ^ 1;
  319.   recycle = (GameCnt % rehash) - rehash;
  320.   /* if background mode set to infinite */
  321.   if (iop == 2)
  322.     {
  323.       Sdepth2 = 0;
  324. #ifdef AMIGA
  325.       (void)SetTaskPri((struct Task *)myproc,0);
  326. #endif
  327.       OrigResponse = ResponseTime = 9999999;
  328. #ifdef QUIETBACKGROUND
  329.       background = true;
  330. #endif /* QUIETBACKGROUND */
  331.     }
  332.   else
  333.     {
  334.       player = side;
  335.       if (TCflag)
  336.     {
  337.       TCcount = 0;
  338. #ifdef QUIETBACKGROUND
  339.       background = false;
  340. #endif /* QUIETBACKGROUND */
  341.       if (TimeControl.moves[side] < 1)
  342.         TimeControl.moves[side] = 1;
  343.       /* special case time per move specified */
  344.       if (flag.onemove)
  345.         {
  346.           OrigResponse = ResponseTime = TimeControl.clock[side] - 100;
  347.           TCleft = 0;
  348.         }
  349.       else
  350.         {
  351.           /* calculate avg time per move remaining */
  352.           TimeControl.clock[side] += TCadd;
  353.           ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) * 2) + 1);
  354.           TCleft = (int)ResponseTime / 3;
  355.           ResponseTime += TCadd/2;
  356.           if (TimeControl.moves[side] < 5)
  357.         TCcount = MAXTCCOUNTX - 1;
  358.         }
  359.       if (ResponseTime < 101)
  360.         {
  361.           ResponseTime = 100;
  362.           TCcount = MAXTCCOUNTX;
  363.         }
  364.       else if (ResponseTime < 200)
  365.         {
  366.           TCcount = MAXTCCOUNTX - 1;
  367.         }
  368.       OrigResponse = ResponseTime;
  369.       if ((TimeControl.moves[side] > 9))
  370.        ResponseTime += 51;
  371. //           ResponseTime = ResponseTime + (ResponseTime/4); // ADDED TO 2.50 to make clock better
  372.     }
  373.       else
  374.        {
  375. #ifdef QUIETBACKGROUND
  376.       background = false;
  377. #endif /* QUIETBACKGROUND */
  378.     OrigResponse = ResponseTime = MaxResponseTime;
  379.        }
  380.       if (TCleft)
  381.     {
  382.       TCcount = ((int)((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft;
  383.       if (TCcount > MAXTCCOUNTX)
  384.         TCcount = 0;
  385.       else
  386.         TCcount = MAXTCCOUNTX - TCcount;
  387.     }
  388.       else
  389.     TCcount = MAXTCCOUNTX;
  390.     }
  391.   if (MoveNowOK)
  392.    {
  393.     thinking2 = 1; /* allow move now menu item to work */
  394.    }
  395.   else
  396.    {
  397.     thinking2 = 0; /* do not allow move now menu item to work */
  398.    }
  399. #ifndef OLD_LOOKAHEAD // this is faster for predicted moves
  400.   if (Sdepth > 0) // guessed correct move!
  401.    {
  402.      if (TCflag)
  403.        time0 = time(0L);
  404. #ifdef QUIETBACKGROUND
  405.     if (!background)
  406. #endif /* QUIETBACKGROUND */
  407.      SearchStartStuff ();
  408.     trying_again = 0;
  409.     if ((GameCnt>2)&&(TCflag)&&(global_tmp_score >= (previous_score-50))&&(Sdepth >= GlobalTgtDepth)
  410.       &&(global_tmp_score >= (GameList[GameCnt-1].score - 50)))
  411.      {
  412.       if (Sdepth >= (GameList[GameCnt-1].depth))
  413.        flag.timeout = true;
  414.       goto ForceTheMove2;
  415.      }
  416.     if ((TCflag)||(backsrchaborted))
  417.      {
  418.       goto ForceTheMove2; // for now use 2, it was ForceTheMove before
  419.      }
  420.     else
  421.      {
  422.       goto ForceTheMove2;
  423.      }
  424.    }
  425. #endif
  426.   ExtraTime = 0;
  427.   ExaminePosition ();
  428. //  score = ScorePosition (side);
  429.   stage= -1; /* Force init in UpdateWeights() */
  430.   start_score= Tscore[0]= Tscore[1]= score=
  431.     evaluate (side, 1, 1, 0, -9999, 9999, 0, &InChkDummy);
  432.   start_stage= stage;
  433. #ifdef QUIETBACKGROUND
  434.   if (!background)
  435. #endif /* QUIETBACKGROUND */
  436.     ShowSidetoMove ();
  437. #ifdef notdef
  438.   if (TCflag && TCcount < MAXTCCOUNT)
  439.     if (score < SCORETIME)
  440.       {
  441.     ExtraTime += TCleft;
  442.     TCcount++;
  443.       }
  444. #endif
  445.  
  446. #ifdef QUIETBACKGROUND
  447.   if (!background)
  448. #endif /* QUIETBACKGROUND */
  449.     SearchStartStuff ();
  450.  
  451. #ifdef HISTORY
  452. #ifndef CLEARHISTBETWEENMOVES
  453. // keep hist info between moves, just shift it all over one bit (depth)
  454. tmphistptr = (ULONG *)history;
  455. for(cnt=0;cnt<(32768/4);cnt++)
  456.  {
  457.   tmphistptr[cnt] = ((tmphistptr[cnt] >> 1) & 0x7f7f7f7f);
  458.  }
  459. #else // clear history between moves
  460.   ClearMem(history,sizeof (history));
  461. #endif // clear history between moves
  462. #endif // HISTORY
  463.  
  464.   FROMsquare = TOsquare = -1;
  465.   PV = 0;
  466.   if (iop == 1)
  467.     hint = 0;
  468. //#ifndef AMIGA
  469. //  for (i = 0; i < MAXDEPTH; i++)
  470. //  {
  471. //    PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  472. //   }
  473. //#else
  474.   ClearMem(PrVar,MAXDEPTH*sizeof(PrVar[0]));
  475.   ClearMem(killr0,MAXDEPTH*sizeof(killr0[0]));
  476.   ClearMem(killr1,MAXDEPTH*sizeof(killr1[0]));
  477.   ClearMem(killr2,MAXDEPTH*sizeof(killr2[0]));
  478.   ClearMem(killr3,MAXDEPTH*sizeof(killr3[0]));
  479. //#endif
  480.   /* set initial window for search */
  481.   alpha = score - ((computer == black) ? BAwindow : WAwindow);
  482.   beta = score + ((computer == black) ? BBwindow : WBwindow);
  483.   rpt = 0;
  484.   TrPnt[1] = 0;
  485.   root = &Tree[0];
  486.   MoveList (side, 1);
  487. #ifdef BEFORE4PL70
  488. if(TrPnt[2]-TrPnt[1] == 0){
  489.     /* if no moves and not in check then draw */
  490.   if (!(SqAtakd3 (PieceList[side][0], xside)))
  491.     {
  492.       root->flags |= draw;
  493.       DRAW = CP[87];            /* No moves */
  494.     } else {
  495. #if !defined CLIENT
  496.     flag.quit = 
  497. #endif
  498.     flag.mate = true;
  499.     root->score = -9999;
  500.     }
  501.     if(iop !=2){
  502.     OutputMove(mystr);
  503.     }
  504.     RealThink = 0;
  505.     //ClearPointer(wG);
  506.     return;
  507.     }
  508. #endif // before 4pl70
  509.   for (i = TrPnt[1]; i < TrPnt[2]; i++) pick (i, TrPnt[2] - 1);
  510.   /* can I get a book move? */
  511.   if ((flag.regularstart && Book))
  512.     {
  513.       flag.timeout = bookflag = OpeningBook (&hint, side);
  514.       if (TCflag)
  515.        {
  516.     ResponseTime += ResponseTime;
  517.     OrigResponse = ResponseTime;
  518.        }
  519.     }
  520. #ifdef SPEED_PRECALC
  521.   if ((!flag.timeout)&&(ThinkAheadWorked))
  522.    {
  523.     flag.timeout = DoPreCalc(&hint,side);
  524.    }
  525. #endif
  526.   /* zero stats for hash table */
  527. #ifdef ZEROALLBETWEENPLY
  528. #ifdef OLDTTABLE
  529.   if (!bookflag)
  530.    {
  531.     ZeroTTable();
  532.     EADD = EGET = 0;
  533.    }
  534. #endif
  535. #endif
  536.   reminus = replus = 0;
  537.   GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
  538.   globalscore = plyscore = score;
  539.   zwndw = 20;
  540.   Jscore = trying_again = global_tmp_score = previous_score = 0;
  541. #include "debug4.h"
  542.   /********************* main loop ********************************/
  543.     Sdepth = (MaxSearchDepth<(MINDEPTH-1))?MaxSearchDepth:(MINDEPTH-1);
  544. /*printf("\n\n");*/
  545. //ForceTheMove:
  546.   while (!flag.timeout)
  547.     {
  548. /*printf("time0 = %d et = %d SDepth = %d GameCnt = %d\n",time0, et,Sdepth,GameCnt);*/
  549. /*printf("ThinkAheadWorked = %d  ThinkAheadDepth = %d\n",ThinkAheadWorked,ThinkAheadDepth);*/
  550.       /* go down a level at a time */
  551.       Sdepth++;
  552. #if defined NULLMOVE || defined DEEPNULL
  553.       null = 0;
  554.       PVari = 1;
  555. #endif
  556. //      DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
  557.       DepthBeyond = Sdepth +
  558.     ((Sdepth == 1) ? FBEYOND : flag.threat ? SBEYOND: TBEYOND);
  559.       no_null= (emtl[xside] == 0 || emtl[side] == 0);
  560.  
  561. #if !defined CHESSTOOL && !defined XBOARD
  562. #ifdef QUIETBACKGROUND
  563.       if (!background)
  564. #endif /* QUIETBACKGROUND */
  565.     ShowDepth (); 
  566. #endif
  567.       root->score= Tscore[0]= Tscore[1]= start_score;
  568.       /* search at this level returns score of PV */
  569. //      score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt, QBLOCK);
  570.       score = search (side, 1, Sdepth, 0, alpha, beta, PrVar, &rpt, QBLOCK, false);
  571.       /* save PV as killer */
  572.       for (i = 1; i <= Sdepth; i++)
  573.     killr0[i] = PrVar[i];
  574.  
  575.       /* low search failure re-search with (-inf,score) limits  */
  576.       if (score < alpha)
  577.     {
  578. #if !defined CHESSTOOL && !defined XBOARD
  579.       reminus++;
  580. #ifdef QUIETBACKGROUND
  581.       if (!background)
  582. #endif /* QUIETBACKGROUND */
  583.         ShowDepth ();
  584. #endif
  585.       if (TCflag && TCcount < MAXTCCOUNTR)
  586.         {
  587.           TCcount = MAXTCCOUNTR - 1;
  588.           ExtraTime += (8 * TCleft);
  589.         }
  590. // root->score commented out on 4pl71 FIX!!!
  591.       /*root->score= */Tscore[0]= Tscore[1]= start_score;
  592.       score = search (side, 1, Sdepth, 0, -9999, 9999, PrVar, &rpt,QBLOCK,false);
  593.     }
  594.       /* high search failure re-search with (score, +inf) limits */
  595.       else if (score > beta && !(root->flags & exact))
  596.     {
  597. #if !defined CHESSTOOL && !defined XBOARD
  598.       replus++;
  599. #ifdef QUIETBACKGROUND
  600.       if (!background)
  601. #endif /* QUIETBACKGROUND */
  602.         ShowDepth ();
  603. #endif
  604. // root->score commented out on 4pl71 fix
  605.       /*root->score=*/ Tscore[0]= Tscore[1]= start_score;
  606.       score = search (side, 1, Sdepth, 0, -9999, 9999, PrVar, &rpt,QBLOCK,false);
  607.     }
  608.       /**************** out of search ********************************************/
  609. ForceTheMove2:
  610.       if ((flag.timeout)||(flag.musttimeout)||(flag.back))
  611.        earlyflag = true;
  612.       else
  613.        earlyflag = false;
  614.       if (flag.musttimeout || Sdepth >= MaxSearchDepth)
  615.        {
  616.     flag.timeout = true;
  617.        }
  618.       else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
  619.     {
  620.       if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */ )
  621.         {
  622.           TCcount++;
  623.           ExtraTime += TCleft;
  624.         }
  625.       if ((abs (score - globalscore) / Sdepth) > ZDELTA)
  626.         {
  627.           TCcount++;
  628.           ExtraTime += TCleft;
  629.         }
  630.     }
  631.       if (score > (Jscore - zwndw) && score > (Tree[1].score + 250)) ExtraTime = 0;
  632. /*printf("sdepth = %d mindepth = %d TCflag = %d \n4*et = %d respt = %d extra = %d\n",Sdepth,MINDEPTH,TCflag,4*et,ResponseTime,ExtraTime);*/
  633. // || rpt > 1 added with 4pl71
  634.       if (root->flags & exact || rpt > 1) flag.timeout = true;
  635.       /*else if (Tree[1].score < -9000) flag.timeout = true;*/
  636.       else if (!(Sdepth < MINDEPTH) && TCflag && ((4 * et) > (2*ResponseTime + ExtraTime))) flag.timeout = true;
  637.       /************************ time control ***********************************/
  638.  
  639.       /* save PV as killer */
  640.       for (i = 1; i <= Sdepth + 1; i++) killr0[i] = PrVar[i];
  641.       if (!flag.timeout) start_score = Tscore[0] = score;
  642.       /* if (!flag.timeout) */
  643. //      for (i = TrPnt[1]+1; i < TrPnt[2]; i++) if (!pick (i, TrPnt[2] - 1)) break;
  644.       /* if done or nothing good to look at quit */
  645.       if ((root->flags & exact) || (score < -9000)) flag.timeout = true;
  646.       /* find the next best move put below root */
  647. #include "debug13.h"
  648.       if (!flag.timeout)
  649.     {
  650.       /* */
  651. #if !defined NODYNALPHA
  652.       Jscore = (plyscore + score) >> 1;
  653. #endif
  654.       zwndw = 20 + abs (Jscore / 12);
  655.       plyscore = score;
  656.       /* recompute search window */
  657.       beta = score + ((computer == black) ? BBwindow : WBwindow);
  658. #if !defined NODYNALPHA
  659.       alpha = ((Jscore < score) ? Jscore : score) - ((computer == black) ? BAwindow : WAwindow) - zwndw;
  660. #else
  661.       alpha = score - ((computer == black) ? BAwindow : WAwindow);
  662. #endif
  663.     }
  664. #if !defined CHESSTOOL && !defined XBOARD
  665. #ifdef QUIETBACKGROUND
  666.       if (!background)
  667. #endif /* QUIETBACKGROUND */
  668.     ShowResults (score, PrVar);
  669. #ifdef DEBUG41
  670.       debug41 (score, PrVar, '.');
  671. #endif
  672. #endif
  673. #include "debug16.h"
  674. #ifdef CHECKMOVERESULTS
  675.       if ((score >= 11000)&&(!got_20000))
  676.        {
  677.     got_20000 = 1;
  678.     Sdepth = 0;
  679.     goto start_again;
  680.        }
  681.       if (((flag.timeout)&&((!PrVar[1])||(!PrVar[2]))&&(!(root->flags & exact))&&(iop != 2)&&(abs(score) < 9000)&&(abs(score)>25))) /* do not trust this move! */
  682.        {
  683.     if ((Sdepth > 2))
  684.      {
  685.       if ((earlyflag))
  686.        {
  687.         Sdepth--;
  688.        }
  689.       if (!trying_again)
  690.        { /* this is first bogus move we have seen */
  691.         ResponseTime = ResponseTime << 1;
  692.         ExtraTime += 251;
  693.        }
  694.       else
  695.        { /* this is not 1st bogus move we have seen */
  696.         ExtraTime += 201;
  697.        }
  698.       trying_again = 1;
  699.       flag.timeout = false;
  700.       flag.back = false;
  701.       flag.musttimeout = false;
  702.      }
  703.        }
  704.       else if (trying_again) /* this move is trustworthy, to an extent */
  705.        {
  706.     if ((TCflag && ((4 * et) > (ResponseTime + ExtraTime - 251)))||(root->flags & exact)) 
  707.      flag.timeout = true;
  708.        }
  709. #endif
  710.       previous_score = score;
  711.     } /* while !flag.timeout */
  712.   /******************************* end of main loop ***********************************/
  713.   /* background mode */
  714.   if (iop == 2)
  715.    {
  716.     if (bookflag) Sdepth = 0;
  717.     if (!flag.easy)
  718.      {
  719.       Sdepth2 = Sdepth;
  720.       if (Sdepth2 > (GlobalTgtDepth+1))
  721.        Sdepth2--;
  722. #ifdef SPEED_PRECALC
  723.       PreCalcedMove = (Tree[TrPnt[1]].f << 8) | (Tree[TrPnt[1]].t);
  724.       PreCalcedHint = ((PrVar[1]) ? PrVar[2] : 0);
  725. #endif
  726.      }
  727.     RealThink = 0;
  728.     //ClearPointer(wG);
  729.     return;
  730.    }
  731. #include "debug4.h"
  732. #ifdef PRE4PL70
  733.   if (rpt >= 2)
  734.     {
  735.       root->flags |= draw;
  736.       DRAW = CP[101];           /* Repetition */
  737.     }
  738.   else
  739.     /* if no moves and not in check then draw */
  740. #endif // PRE4pl70
  741.    if ((score == -9999) && !(SqAtakd3 (PieceList[side][0], xside))) // was 9998
  742.     {
  743.       root->flags |= draw;
  744.       DRAW = CP[87];            /* No moves */
  745.     }
  746.   else if (GameCnt == MAXMOVES)
  747.     {
  748.       root->flags |= draw;
  749.       DRAW = CP[80];            /* Max Moves */
  750.     }
  751.   /* not in book so set hint to guessed move for other side */
  752.   if (!bookflag)
  753.    {
  754.     hint = ((PrVar[1]) ? PrVar[2] : 0);
  755.    }
  756.   else if ((!Book)||(!flag.regularstart))
  757.    bookflag = 0;
  758.  
  759.   algbr (root->f, root->t, (short) root->flags);
  760.   /* if not mate or draw make move and output it */
  761.   if (((score != -9999)  && (score != 9998) && (rpt <= 2)) || (root->flags & draw))
  762.     {
  763.       MakeMove (side, &Tree[0], &tempb, &tempc, &tempsf, &tempst, &INCscore);
  764. #if !defined NOMATERIAL
  765.       if (flag.material && !pmtl[black] && !pmtl[white] && (mtl[white] < (valueR + valueK)) && (mtl[black] < (valueR + valueK)))
  766.     {
  767.       root->flags |= draw;
  768.       DRAW = CP[224];       /* No pieces */
  769.     }
  770.       else
  771. #endif
  772.       if (!PieceCnt[black] && !PieceCnt[white])
  773.     {
  774.       root->flags |= draw;
  775.       DRAW = CP[88];        /* No pieces */
  776.     }
  777.     }
  778.   else
  779.     { root->score = score;      /* When mate, ignore distinctions! * --SMC */
  780.     }
  781.  
  782.   g = &GameList[GameCnt];
  783.   if (g->flags & capture && g->piece == king)
  784.     {
  785.       flag.mate = flag.illegal = true;
  786.     }
  787.   /* If Time Control get the elapsed time */
  788.   if (TCflag)
  789.     ElapsedTime (1);
  790.   /* if mate set flag */
  791. // this line added from 4pl71 code!
  792.    if (rpt > 1) root->flags |= (draw | exact);
  793.  
  794.    if (score == -9999 || rpt > 1)
  795.      mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = mvstr[4][0] = '\0';
  796.     /* if mate set flag */
  797.   if ((score == -9999) || (score == 9998)) {flag.mate = true; 
  798. #ifndef CLIENT
  799. #ifndef AMIGA
  800. //???        flag.quit = true;
  801. #endif
  802. #endif
  803.     }
  804.   OutputMove ();     
  805.   /* if mate clear hint */
  806.   if (flag.mate)
  807.     hint = 0;
  808.   /* if pawn move or capture or castle or promote zero repitition array */
  809.   if ((board[root->t] == pawn) || (root->flags & (capture | cstlmask | promote)))
  810.     {
  811.       Game50 = GameCnt;
  812.       ZeroRPT ();
  813.     }
  814.   /* add move to game list */
  815.   g->score = score;
  816.   g->nodes = NodeCnt;
  817.   g->time = (et +50)/100;
  818.   g->depth = Sdepth;
  819. #include "debug40.h"
  820.   /* update time comtrol info */
  821.   if (TCflag)
  822.     {
  823. #if defined CHESSTOOL || defined XBOARD
  824.       TimeControl.clock[side] -= (et + OperatorTime + 45);
  825.       timecomp[compptr] = (et + OperatorTime + 45);
  826. #else
  827.       TimeControl.clock[side] -= (et + OperatorTime);
  828.       timecomp[compptr] = (et + OperatorTime);
  829. #endif
  830.       /* finished our required moves - setup the next set */
  831.       --TimeControl.moves[side];
  832.     }
  833.   /* check for end conditions */
  834.   if ((root->flags & draw) /* && flag.bothsides */ )
  835. #if !defined CLIENT
  836.      flag.mate = true;
  837. #else 
  838.     ;
  839. #endif
  840.   else if (GameCnt == MAXMOVES)
  841.     {
  842.       flag.mate = true;
  843.     }
  844.   /* out of move store, you loose */
  845.   else
  846.     /* switch to other side */
  847.     player = xside;
  848.   Sdepth = 0;
  849.   RealThink = 0;
  850.   //ClearPointer(wG);
  851. }
  852.  
  853. int
  854. search (short int side,
  855.     register short int ply,
  856.     register short int depth,
  857.     short ext,
  858.     short int alpha,
  859.     short int beta,
  860.     short unsigned int *bstline,
  861.     short int *rpt,
  862.     short SAVEHT,
  863.     int didnull)
  864.  
  865. /*
  866.  * Perform an alpha-beta search to determine the score for the current board
  867.  * position. If depth <= 0 only capturing moves, pawn promotions and
  868.  * responses to check are generated and searched, otherwise all moves are
  869.  * processed. The search depth is modified for check evasions, certain
  870.  * re-captures and threats. Extensions may continue for up to 11 ply beyond
  871.  * the nominal search depth.
  872.  */
  873.  
  874.  
  875. {
  876.   register short j, pnt;
  877.   short tempb, tempc, tempsf, tempst;
  878.   short xside, pbst, score, rcnt, InChk;
  879.   unsigned short mv, nxtline[MAXDEPTH];
  880.   struct leaf *node, tmp;
  881.   short best = -12000;
  882. #ifdef DOIT_4PL68WAY // this is the 4pl68 way to extend search
  883.   int __aligned max_time;
  884. #endif
  885.   short bestwidth = 0;
  886. #if defined NULLMOVE || defined DEEPNULL
  887.   short int __aligned PVsave;
  888.   short int __aligned PVarisave;
  889.   unsigned short __aligned verydeep=0xffff;
  890. #endif
  891. #ifdef DEBUG
  892.   int xxxtmp;
  893.   int tracetmp;
  894. #endif
  895.   short __aligned extdb= 0;
  896.   short __aligned threat= 0;      /* tom@izf.tno.nl */
  897.   short __aligned threat2= 0;     /* tom@izf.tno.nl */
  898.   short __aligned do_pvs;
  899.  
  900.   NodeCnt++;
  901.   /* look every ZNODE nodes for a timeout */
  902.   if (!null)
  903.    {
  904.   if (NodeCnt > ETnodes )
  905.     {
  906.       ElapsedTime (2);
  907.       if (flag.back)
  908.     {
  909.       flag.back = false;
  910.       flag.timeout = true;
  911.       flag.musttimeout = false;
  912.     }
  913.       else if (TCflag || MaxResponseTime)
  914.     {
  915.       if ((et >= (ResponseTime + ExtraTime)) && Sdepth > MINDEPTH && abs(best) < 10000)
  916.         {                   /* try to extend to finish ply */
  917. #define TRYEXTEND 1
  918. #ifdef TRYEXTEND
  919.           if ((TCflag && TCcount < MAXTCCOUNTX)&&(GameCnt > 10))
  920.         {
  921.           flag.musttimeout = true;
  922.           TCcount += 1;
  923.           ExtraTime += TCleft;
  924.         }
  925.           else
  926.         {
  927.           flag.timeout = true;
  928.           flag.musttimeout = false;
  929.         }
  930. #else
  931.           if ((TCflag && TCcount < MAXTCCOUNTX)&&(flag.easy))
  932.         {
  933.           flag.musttimeout = true;
  934.           TCcount += 1;
  935.           ExtraTime += TCleft;
  936.         }
  937.           else
  938.         {
  939.           flag.timeout = true;
  940.           flag.musttimeout = false;
  941.         }
  942. #endif
  943.         }
  944.     }
  945.     }
  946.   else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH)
  947.     {
  948.       flag.timeout = true;
  949.       flag.musttimeout = false;
  950.     }
  951.    } // !null
  952.   xside = side ^ 1;
  953.   if (ply == 1) INCscore = 0; // TMP!! MY Fix for INCscore not init at ply 1
  954.   /* slk is lone king indicator for either side */
  955.   score = evaluate (side, ply, depth, ext, alpha, beta, INCscore, &InChk);
  956.  
  957.   /*
  958.    * check for possible repitition if so call repitition - rpt is
  959.    * repeat count
  960.    */
  961.   if (ProbeRPThash(side,hashkey))
  962.     {
  963.       *rpt = repetition ();
  964.       if (*rpt == 1) score = -contempt;
  965. // next line changed from *rpt > 2 to *rpt > 1 in 4pl71
  966.       else if (*rpt > 1) {
  967.       bstline[ply] = 0;
  968.       return (-contempt);
  969.     }
  970.     }
  971.   else
  972.     *rpt = 0;
  973.  
  974.   /* score > 9000 its a draw or mate */
  975.   if (score > 9000 /*|| root->flags & draw*/) // was commented out is back in with 4pl70
  976.     {
  977.       bstline[ply] = 0;
  978.       return (score);
  979.     }
  980.   /* Do we need to add depth because of special conditions */
  981.   /* if in check or pawn threat or in capture sequence search deeper */
  982.   /*************************************** depth extensions ***********************************/
  983. #ifdef OLDEXT
  984.   if (depth > 0)
  985.     {
  986.       /* Allow opponent a chance to check again */
  987.       if (InChk)
  988.     depth = (depth < 2) ? 2 : depth;
  989.       else if (PawnThreat[ply - 1] ||
  990.            (flag.rcptr && (score > alpha) &&
  991.       (score < beta) && (ply > 2) && CptrFlag[ply - 1] && CptrFlag[ply - 2]))
  992.     ++depth;
  993.     }
  994.   else
  995.     {
  996.       if (score >= alpha &&
  997.       (InChk || PawnThreat[ply - 1] || (hung[side] > 1 /* && ply == Sdepth + 1*/)))
  998.     depth = 1;
  999.       else if (score <= beta &&
  1000.            ((ply < Sdepth + 4) && (ply > 4) &&
  1001.  
  1002.         ChkFlag[ply - 2] && ChkFlag[ply - 4]))
  1003.     {
  1004.           depth = 1;
  1005.     }
  1006.     }
  1007. #else
  1008.  
  1009. #define DOTHREAT    (start_stage < THRSTAGE)
  1010. #define DOCHECK     (start_stage < CHECKSTAGE)
  1011.  
  1012.   Threat[ply]= 0;
  1013.   if (depth > 0)
  1014.     {
  1015.       /* Allow opponent a chance to check again */
  1016.       if (InChk) {
  1017. #ifdef DOIT_4PL68WAY // this is the 4pl68 way to extend search
  1018.       if (TCflag)
  1019.        max_time = ((OrigResponse<<2) + ExtraTime);
  1020.       else
  1021.        max_time = 99999999;
  1022.       if (et >= max_time)
  1023.        {
  1024.         if (flag.threat)
  1025.           depth= DOCHECK && (ply+depth<DepthBeyond-DEPTHMARGIN) ?
  1026.         depth+1: depth;
  1027.         else
  1028.           depth= (depth < 2) ? 2 : depth;
  1029.        }
  1030.       else
  1031.        depth++;
  1032. #else // this is the Kong Sian way, always extend check search
  1033.       // this way costs more time but may be better
  1034.       depth++;
  1035. #endif
  1036.       }
  1037.       else if ((ply>1 && PawnThreat[ply - 1] && ply+depth<DepthBeyond-DEPTHMARGIN) ||
  1038.            (flag.rcptr && ply>2 && CptrFlag[ply - 1] && CptrFlag[ply - 2] &&
  1039.            ((ply<Sdepth+2 && CptrFlag[ply-1]==CptrFlag[ply-2]) ||
  1040. // the next line is a fix from Kong Sian, old way may be better
  1041.         (score > root->score - valueP/4 && score < root->score + valueP/4))) // FIX by Kong SIAN
  1042. //               (score > alpha && score < beta))) // OLD 4PL68 way
  1043.            )
  1044.       ++depth;
  1045.     }
  1046.   else
  1047.     { 
  1048.       int tripple_check = 0;
  1049.       if (score >= alpha &&
  1050.       (InChk || (ply>1 && PawnThreat[ply - 1] && depth<DepthBeyond-4)
  1051.       || (hung[side] > 1 /*&& !ext*/))) { // fix from Kong Sian
  1052.     threat2= 1;
  1053.     ext++;
  1054.     depth= 1;
  1055.       }
  1056.       else if (score <= beta &&
  1057.            ((ply<Sdepth+4 && ply>4 &&
  1058.         ChkFlag[ply-2] && ChkFlag[ply-4] &&
  1059.         (ChkFlag[ply-2] != ChkFlag[ply-4] ||
  1060.         (flag.threat && DOTHREAT && QueenCheck[ply-2])))
  1061.       ||
  1062.         (flag.threat && ply<DepthBeyond-DEPTHMARGIN && ply>6
  1063.         && ChkFlag[ply-2] && ChkFlag[ply-4] && ChkFlag[ply-6]
  1064.         &&  (tripple_check=1)
  1065.         && ((ply < Sdepth+4 ?
  1066.           (ChkFlag[ply-2] != ChkFlag[ply-4] || ChkFlag[ply-2] !=
  1067. ChkFlag [ply-6])
  1068.           : (ChkFlag[ply-2] != ChkFlag[ply-4] &&
  1069.              ChkFlag[ply-2] != ChkFlag[ply-6] &&
  1070.              ChkFlag[ply-4] != ChkFlag[ply-6]))
  1071.         || (DOTHREAT && QueenCheck[ply-2]
  1072.         && QueenCheck[ply-4] && QueenCheck[ply-6]
  1073.         && QueenCheck[ply-2] != QueenCheck[ply-6]))
  1074.         ))) {
  1075.       if (tripple_check && DepthBeyond < Sdepth+13+DEPTHMARGIN)
  1076.         {
  1077.           extdb += 2;
  1078.           DepthBeyond += 2;
  1079.         }
  1080.       depth= 1;
  1081.       ext++;
  1082.       Threat[ply]= threat= 1;
  1083.     }
  1084.     }    
  1085.   ThreatSave[ply]= ((ply>1 && ThreatSave[ply-1]) || threat);
  1086. #endif
  1087.   /*******************************************************************************************/
  1088.   /* try the local transition table if it's there */
  1089.   if (ply>1) TrPnt[ply+1]= TrPnt[ply]; // TMP!! My Fix for move gen
  1090.  
  1091.   /*
  1092.    * if more then DepthBeyond ply past goal depth or at goal depth and
  1093.    * score > beta quit - means we are out of the window
  1094.    */
  1095.   if (ply > DepthBeyond || (depth < 1 && score > beta))
  1096.     {
  1097.       return (score);
  1098.     }
  1099. #if defined ttblsz
  1100.       if ( flag.hash && ply > 1) // fix from Kong Sian
  1101.         {
  1102.         if (ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true)
  1103.           {
  1104.               if (beta == -20000 || alpha > beta)
  1105.             {
  1106.                 bstline[ply] = PV;
  1107.                 bstline[ply + 1] = 0;
  1108.                 /*
  1109.                  * make sure the move is in the
  1110.                  * MoveList
  1111.                  */
  1112.                 if (ply == 1)
  1113.                   {   
  1114.                   struct leaf tmp;
  1115.                   register int spnt;
  1116.                   for (spnt = TrPnt[ply]; spnt < TrPnt[ply + 1]; spnt++)
  1117.                     {
  1118.                     if (((Tree[spnt].f << 8) | Tree[spnt].t) == PV)
  1119.                       {
  1120.                           if (ply == 1 && Tree[spnt].score == DONTUSE) {bstline[1] = 0; break;}
  1121.                           Tree[spnt].score = (beta == -20000) ? score : alpha;
  1122.                           if (abs (score) > 9000) Tree[spnt].flags |= exact;
  1123.                           if (spnt != TrPnt[ply])
  1124.                         {
  1125.                             tmp = Tree[TrPnt[ply]];
  1126.                             Tree[TrPnt[ply]] = Tree[spnt];
  1127.                             Tree[spnt] = tmp;
  1128.                         }
  1129. #include "debug64.h"
  1130.                           if (beta == -20000) return (score);
  1131.                           else return (alpha);
  1132.                       }
  1133.                     }
  1134.                   } else {
  1135.                 register int i = TrPnt[ply];
  1136.                 Tree[i].t = PV & 0x3f;
  1137.                 Tree[i].f = PV>>8;
  1138.                 Tree[i].flags = 0;
  1139.                 Tree[i].reply = 0;
  1140.                 Tree[i].score = (beta == -20000) ? score : alpha; 
  1141.                 TrPnt[ply+1] = i+1;
  1142.                 if (abs (score) > 9000) Tree[i].flags |= exact; 
  1143.                 if (beta == -20000) return (score); 
  1144.                     else return (alpha); 
  1145.                   }
  1146.  
  1147.             }
  1148.           }
  1149. #ifdef HASHFILE
  1150.         /* ok try the transition file if its there */
  1151.         else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  1152.              && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
  1153.           {
  1154.               if (beta == -20000 || alpha > beta)
  1155.             {
  1156.                 bstline[ply] = PV;
  1157.                 bstline[ply + 1] = 0;
  1158.                 /*
  1159.                  * make sure the move is in the
  1160.                  * MoveList
  1161.                  */
  1162.                 if (ply == 1)
  1163.                   {
  1164.                   struct leaf tmp;
  1165.                   register int spnt;
  1166.                   for (spnt = TrPnt[ply]; spnt < TrPnt[ply + 1]; spnt++)
  1167.                     {
  1168.                     if (((Tree[spnt].f << 8) | Tree[spnt].t) == PV)
  1169.                       {
  1170.                           if (ply == 1 && Tree[spnt].score == DONTUSE) {bstline[1] = 0; break;}
  1171.                           Tree[spnt].score = (beta == -20000) ? score : alpha;
  1172.                           if (abs (score) > 9000) Tree[spnt].flags |= exact;
  1173.                           if (spnt != TrPnt[ply])
  1174.                         {
  1175.                             tmp = Tree[TrPnt[ply]];
  1176.                             Tree[TrPnt[ply]] = Tree[spnt];
  1177.                             Tree[spnt] = tmp;
  1178.                         }
  1179.                           PutInTTable (side, score, depth, ply, /*alpha,*/ beta, PV);
  1180. #include "debug10.h"
  1181.                           if (beta == -20000) return (score);
  1182.                           else return (alpha);
  1183.                       }
  1184.                     }
  1185.                    } else {
  1186.                 register int i = TrPnt[ply];
  1187.                 Tree[i].t = PV & 0x3f;
  1188.                 Tree[i].f = PV>>8;
  1189.                 Tree[i].score = (beta == -20000) ? score : alpha;
  1190.                 TrPnt[ply+1] = i+1;
  1191.                 if (abs (score) > 9000) Tree[i].flags |= exact;
  1192.                 if (beta == -20000) return (score);
  1193.                     else return (alpha);
  1194.                   }
  1195.  
  1196.  
  1197.             }
  1198.           }
  1199. #endif // HASHFILE
  1200.      }
  1201. #endif /* ttblsz */
  1202.       if (depth > 0 || (background && ply < Sdepth + 2)) {if(ply >1)
  1203. #ifdef LEGAL
  1204.         VMoveList (side, ply);}
  1205. #else
  1206.         MoveList (side, ply);}
  1207. #endif
  1208.     else
  1209.       {
  1210. #ifdef LEGAL
  1211.         VCaptureList (side, ply);
  1212. #else
  1213.         CaptureList (side, ply);
  1214. #endif
  1215.     if(!SAVEHT)SAVEHT = ply;
  1216.       }
  1217.  
  1218.  
  1219.  
  1220.   /* no moves return what we have */
  1221.  
  1222.   /*
  1223.    * normally a search will continue til past goal and no more capture
  1224.    * moves exist
  1225.    */
  1226.   /* unless it hits DepthBeyond */
  1227.   if (TrPnt[ply] == TrPnt[ply + 1]) { if(!InChk) return (score); else return (-10001+ply); }
  1228.  
  1229.  
  1230.  
  1231.   /* if not at goal set best = -inf else current score */
  1232.      best = (depth >0) ? -12000:score;
  1233. #ifdef NULLMOVE
  1234.  
  1235.   PVarisave = PVari;
  1236.   if (!null &&                         /* no previous null-move */
  1237.       !PVari &&                        /* no null-move during the PV */
  1238.       (ply > 1) && // was 2 changed by Kong Sian
  1239.       (ply <= Sdepth) &&                       /* not at ply 1 */
  1240.       (depth > 2) && // changed by Kong Sian   /* not during the quienscesearch */
  1241.       !InChk &&                        /* no check */
  1242.       ((mtl[side] + mtl[xside]) > NULLMOVELIM))
  1243.     /* enough material such that zugzwang is unlike but who knows which value
  1244.        is suitable? */
  1245.     {
  1246.       
  1247.       /* ok, we make a null move, i.e.  this means we have nothing to do
  1248.      but we have to keep the some arrays up to date otherwise gnuchess
  1249.      gets confused.  Maybe somebody knows exactly which informations are
  1250.      important and which not.
  1251.  
  1252.      Another idea is that we try the null-move first and generate the
  1253.      moves later.  This may save time but we have to take care that
  1254.      PV and other variables contain the right value so that the move
  1255.      ordering works right.
  1256.      */
  1257.       register struct GameRec *g;
  1258.       
  1259.       nxtline[ply + 1] = 0;
  1260.       CptrFlag[ply] = 0;
  1261.       PawnThreat[ply] = 0;
  1262.       Tscore[ply] = score;
  1263.       PVsave = PV;
  1264.       PV = 0;
  1265.       null = 1;
  1266.       g = &GameList[++GameCnt];
  1267.       g->hashkey = hashkey;
  1268.       g->hashbd = hashbd;
  1269.       epsquare = -1;
  1270.       TOsquare = -1;
  1271.       g->Game50 = Game50;
  1272. #ifdef LONGINTS
  1273.       g->gmove = 0xffffffff;
  1274. #else
  1275.       g->gmove = 0xffff;
  1276. #endif
  1277.       g->flags = 0;
  1278.       g->piece = 0;
  1279.       g->color = neutral;
  1280.       
  1281. //      best = -search (xside, ply + 1, false, depth - 2, -beta - 1, -beta, nxtline, &rcnt,false,false);
  1282. //this next line a fix from Kong Sian replaces above line
  1283.       best = -search (xside, ply + 1, false, depth - 2, -beta, -beta, nxtline, &rcnt,false,false);
  1284.       null = 0;
  1285.       PV = PVsave;
  1286.       GameCnt--;
  1287.       if (best < alpha) best = -12000;
  1288.       else if (best > 0 && best > beta) return (best);
  1289.       else
  1290.     best = -12000;
  1291.     }
  1292. #else 
  1293. #ifdef DEEPNULL
  1294.  
  1295.   /*
  1296.    * The deepnull algoritm is taken from the article by
  1297.    * Christian Donninger in ICCA journal Vol 16, No. 3.  TomV
  1298.    */
  1299.   PVarisave = PVari;
  1300.   if ((myflagdeepnull ? !didnull : !null) &&    /* no previous null-move */
  1301.     //  !flag.nonull &&
  1302.       !no_null &&
  1303.       !PVari &&                 /* no null-move during the PV */
  1304.       (ply > (myflagdeepnull ? 1: 2)) &&                /* not at ply 1 */
  1305.       (score > alpha - 150 || !myflagdeepnull) &&
  1306.       (ply <= Sdepth || myflagdeepnull) &&
  1307.       (depth > (myflagdeepnull ? (verydeep ? 1: 2): 3)) &&
  1308.       !InChk &&                 /* no check */
  1309.       /* enough material such that zugzwang is unlikely: */
  1310.       ! (emtl[xside] == 0 || emtl[side] <= valueB))
  1311.     {
  1312.  
  1313.       /* ok, we make a null move, i.e.  this means we have nothing to do
  1314.      but we have to keep the some arrays up to date otherwise gnuchess
  1315.      gets confused.
  1316.  
  1317.      Another idea is that we try the null-move first and generate the
  1318.      moves later.  This may save time but we have to take care that
  1319.      PV and other variables contain the right value so that the move
  1320.      ordering works right.
  1321.      */
  1322.       CptrFlag[ply] = 0;
  1323.       PawnThreat[ply] = 0;
  1324.       Tscore[ply] = score;
  1325.       PVsave = PV;
  1326.       PV = 0;
  1327.       epsquare = -1;
  1328.       TOsquare = -1;
  1329.       if (!null)
  1330.     null= ply;
  1331.       if (myflagdeepnull) {
  1332.     int nmscore = -search (xside, ply + 1, (depth >= 3 ? depth - 3: 0), ext, -beta, -alpha, nxtline, &rcnt,false,1);
  1333.     if (ply == null)
  1334.       null = 0;
  1335.     PV = PVsave;
  1336.     if (nmscore > beta) {
  1337.       DepthBeyond-= extdb;
  1338.       return nmscore;
  1339.     }
  1340.     if (nmscore > alpha)
  1341.       best= nmscore;
  1342.     if (depth <= 3 && ply < DepthBeyond-depth-4
  1343.         && score >= beta && nmscore < score - 350)
  1344.           depth++;
  1345.       } else {
  1346. // change to -beta,-beta from K SIAN
  1347.     best = -search (xside, ply + 1, depth - 2, ext, -beta - 1, -beta, nxtline, &rcnt, false, 1);
  1348. //        best = -search (xside, ply + 1, depth - 2, ext, -beta, -beta, nxtline, &rcnt, false, 1);
  1349.     null = 0;
  1350.     PV = PVsave;
  1351.     if (best < alpha) best = -12000;
  1352.     else if (best > beta) {
  1353.        DepthBeyond-= extdb;
  1354.        return (best);
  1355.     }  else best = -12000;
  1356.       }
  1357.     }
  1358. #endif //deepnull
  1359. #endif // nullmove
  1360.   /* if best so far is better than alpha set alpha to best */
  1361.     if(best>alpha)alpha=best;
  1362.   /********************** main loop ************************************************************************/
  1363.   /* look at each move until no more or beta cutoff */
  1364.    do_pvs = 0;
  1365. //   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] &&
  1366. //    (best <= beta || (ply == 1 && best > 9000)); pnt++) /* Find best mate, TomV TMP!!*/
  1367.   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++)
  1368.     {
  1369.       /* find the most interesting looking of the remaining moves */
  1370.       if (ply > 1)
  1371.     pick (pnt, TrPnt[ply + 1] - 1);
  1372. #if defined NULLMOVE || defined DEEPNULL
  1373.       PVari = PVarisave && (pnt == pbst/*TrPnt[ply]*/);  /* Is this the PV? */
  1374. #endif
  1375.  
  1376.       node = &Tree[pnt];
  1377.       /* is this a forbidden move */
  1378.       if (pnt == pbst)
  1379.        do_pvs = myflagpvs && PVari; // this line a fix from Kong Sian, replaced line below
  1380. //        do_pvs= myflagpvs && !null && (PrVar[ply] == ((node->f << 8) | node->t));
  1381.       if (ply == 1 && node->score == DONTUSE)
  1382.     continue;
  1383. #ifdef DEBUG
  1384.     if(debuglevel & (512 | 1024)){
  1385.         if(!tracen)traceflag = ((ply >traceply)?false:true);
  1386.         else
  1387.         if(ply <= tracen && (ply ==1 || traceflag))
  1388.             { 
  1389.             if(trace[ply] == (Tree[pnt].t |(Tree[pnt].f<<8))) traceflag = true; else traceflag = false; }
  1390.         tracelog[ply] = (Tree[pnt].t |(Tree[pnt].f<<8));
  1391.         tracelog[ply+1] = 0;
  1392. }
  1393. #endif
  1394.       nxtline[ply + 1] = 0;
  1395.  
  1396. #if !defined CHESSTOOL && !defined XBOARD
  1397.       /* if at top level */
  1398.       if (ply == 1)
  1399.     {                       /* at the top update search status */
  1400.       if (flag.post)
  1401. #ifdef QUIETBACKGROUND
  1402.         if (!background)
  1403. #endif /* QUIETBACKGROUND */
  1404.           ShowCurrentMove (pnt, node->f, node->t);
  1405.     }
  1406. #endif
  1407.       /* make the move and go deeper */
  1408.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  1409. // FIX from Kong Sian for cpt flag
  1410. //        CptrFlag[ply] = (node->flags & capture); // OLD way
  1411.       CptrFlag[ply] = (node->flags & capture ? TOsquare+1 : 0); // K. Sian way
  1412.       PawnThreat[ply] = (node->flags & pwnthrt);
  1413.       Tscore[ply] = node->score;
  1414.       PV = node->reply;
  1415. #ifdef DEBUG
  1416.       xxxtmp = node->score;
  1417.       tracetmp = traceflag;
  1418. #endif
  1419.       if (/*flag.pvs && */depth > 0) { /* From Kong Sian OS/2 */
  1420.       //if (do_pvs) {  // Old Line replaced by above
  1421.         if (pbst == pnt) {
  1422.           node->score= -search (xside, ply + 1,
  1423.                  depth > 0 ? depth - 1 : 0, ext,
  1424.                  -beta, -alpha,
  1425.                  nxtline, &rcnt,SAVEHT, 0);
  1426.         } else {
  1427.           node->score= -search(xside, ply + 1,
  1428.                   depth > 0 ? depth - 1 : 0, ext,
  1429.                   -alpha-1, -alpha,
  1430. // below line is a fix from Kong Sian, replaces above line
  1431. //                              -alpha, -alpha,
  1432.                   nxtline, &rcnt,SAVEHT, 0);
  1433. // next if stmt improved by Kong Sian after 4pl68
  1434.           if (/*node->score >= best && */alpha <= node->score
  1435.           /*&& node->score <= beta*/)
  1436.           node->score = -search (xside, ply + 1,
  1437.                  depth > 0 ? depth - 1 : 0, ext,
  1438.                  -beta, /*-node->score*/-alpha,
  1439.                  nxtline, &rcnt,SAVEHT, 0);
  1440.         }
  1441.       } else
  1442.  
  1443.       node->score = -search (xside, ply + 1,
  1444.                  (depth > 0) ? depth - 1 : 0, ext,
  1445.                  -beta, -alpha,
  1446.                  nxtline, &rcnt, SAVEHT, false);
  1447.       node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
  1448.       if (abs (node->score) > 9000) node->flags |= exact;
  1449.       else if (rcnt == 1) node->score = 0;
  1450.       if(node->score == (9999-ply) && !ChkFlag[ply] ) {node->flags |= draw;
  1451.           node->score = (-contempt);}
  1452. #include "debug256.h"
  1453.       if ((rcnt >= 2 || GameCnt - Game50 > 99 
  1454. /*|| (node->score == 9999 - ply && !ChkFlag[ply])*/
  1455.           ))
  1456.         {
  1457.           node->flags |= (draw | exact);
  1458.           DRAW = CP[58];    /* Draw */
  1459.           node->score = -contempt;
  1460.         }
  1461.       node->reply = nxtline[ply + 1];
  1462.       /* reset to try next move */
  1463.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1464.       /* if best move so far */
  1465.       if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
  1466.     {
  1467.       /*
  1468.        * all things being equal pick the denser part of the
  1469.        * tree
  1470.        */
  1471.       bestwidth = node->width;
  1472.  
  1473.       /*
  1474.        * if not at goal depth and better than alpha and not
  1475.        * an exact score increment by depth
  1476.        */
  1477.       if (depth > 0 && node->score > alpha && !(node->flags & exact))
  1478.         node->score += depth;
  1479.       best = node->score;
  1480.       pbst = pnt;
  1481.       if (best > alpha) { alpha = best; }
  1482.       /* update best line */
  1483.       for (j = ply + 1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
  1484.       bstline[j] = 0;
  1485.       bstline[ply] = (node->f << 8) | node->t;
  1486.       /* if at the top */
  1487.       if (ply == 1)
  1488.         {
  1489.           /*
  1490.            * if its better than the root score make it
  1491.            * the root
  1492.            */
  1493. // next line has || pnt > 0 added in pl71
  1494.           if ((best > root->score) || ((best == root->score) && (bestwidth > 
  1495.           root->width)) || pnt > 0)
  1496.         {
  1497.           tmp = Tree[pnt];
  1498.           for (j = pnt - 1; j >= 0; j--) Tree[j + 1] = Tree[j];
  1499.           Tree[0] = tmp;
  1500.           pbst = 0;
  1501.         }
  1502.           if (Sdepth > 2)
  1503.            global_tmp_score = best;
  1504. #if !defined CHESSTOOL && !defined XBOARD
  1505. #ifdef QUIETBACKGROUND
  1506.           if (!background)
  1507. #endif /* QUIETBACKGROUND */
  1508.         if (Sdepth > 2)
  1509.           if (best > beta)
  1510.             {
  1511.               ShowResults (best, bstline);
  1512. #ifdef DEBUG41
  1513.               debug41 (best, bstline, '+');
  1514. #endif
  1515.             }
  1516.           else if (best < alpha)
  1517.             {
  1518.               ShowResults (best, bstline);
  1519. #ifdef DEBUG41
  1520.               debug41 (best, bstline, '-');
  1521. #endif
  1522.             }
  1523.           else
  1524.            {
  1525.             ShowResults (best, bstline);
  1526.            }
  1527. #ifdef DEBUG41
  1528.           debug41 (best, bstline, '&');
  1529. #endif
  1530. #else
  1531.        if ((!background) && (Sdepth >2) && (best < alpha)){
  1532.         TCcount = 0;
  1533.         ExtraTime += 20*TCleft;
  1534.        }
  1535. #endif
  1536.         }
  1537.     }
  1538.       if (flag.timeout)
  1539.     {
  1540.       DepthBeyond-= extdb;
  1541. #if defined NULLMOVE || defined DEEPNULL
  1542.   PVari = PVarisave;
  1543. #endif
  1544.       return (Tscore[ply - 1]);
  1545.     }
  1546.     }
  1547.  
  1548.   /******************************************************************************************/
  1549. // this best == -10000 line added in 4pl71
  1550.   if (best == -10000+ply) bstline[ply] = 0;
  1551.   node = &Tree[pbst];
  1552.   mv = (node->f << 8) | node->t;
  1553. #if defined NULLMOVE || defined DEEPNULL
  1554.   PVari = PVarisave;
  1555. #endif
  1556. #ifdef DEBUG
  1557. #include "debug512.h"
  1558. #endif
  1559.  
  1560.   /*
  1561.    * we have a move so put it in local table - if it's already there
  1562.    * done else if not there or needs to be updated also put it in
  1563.    * hashfile
  1564.    */
  1565. #if ttblsz
  1566.   if (flag.hash && !SAVEHT  /*&& ply <= Sdepth*/ && *rpt == 0 && best == alpha)
  1567.     {
  1568.       PutInTTable (side, best, depth, SAVEHT?SAVEHT:ply, /*alpha,*/ beta, mv);
  1569.     }
  1570. #endif /* ttblsz */
  1571.  
  1572.   if (depth > 0)
  1573.     {
  1574. #ifdef HISTORY
  1575.       j = (node->f << 8) | node->t; // was 6 should be 8
  1576.       if (side == black)
  1577.     j |= 0x4000;
  1578. // BELOW IS NEWEST WAY TO UPDATE HISTORY TABLE, AFTER 4PL69
  1579. #ifndef CLEARHISTBETWEENMOVES
  1580.       if (history[j] < HISTORYLIM)
  1581.     history[j] |= (unsigned short) 1 << depth;
  1582. #else
  1583. // below is original way
  1584.       if (history[j] < HISTORYLIM)
  1585.     history[j] |= (unsigned short) 1<<depth;
  1586. // here is a Kong Sian fix from after 4pl68
  1587. //      if (history[j] < ((unsigned short) 1 << depth))
  1588. //        history[j] = ((unsigned short) 1 << depth);
  1589. #endif
  1590.  
  1591. #endif
  1592.       if (node->t != (short)(GameList[GameCnt].gmove & 0xFF))
  1593.     if (best <= beta)
  1594.       killr3[ply] = mv;
  1595.     else if (mv != killr1[ply])
  1596.       {
  1597.         killr2[ply] = killr1[ply];
  1598.         killr1[ply] = mv;
  1599.       }
  1600.       killr0[ply] = ((best > 9000) ? mv : 0);
  1601.     }
  1602.  
  1603.   DepthBeyond -= extdb; // this LINE added after 4pl68 by Kong Sian
  1604.  
  1605.   return (best);
  1606. }
  1607.  
  1608.  
  1609.  
  1610. int
  1611. castle (short side, short kf, short kt, short iop)
  1612.  
  1613. /* Make or Unmake a castling move. */
  1614.  
  1615. {
  1616.   register short rf, rt, t0, xside;
  1617.  
  1618.   xside = side ^ 1;
  1619.   if (kt > kf)
  1620.     {
  1621.       rf = kf + 3;
  1622.       rt = kt - 1;
  1623.     }
  1624.   else
  1625.     {
  1626.       rf = kf - 4;
  1627.       rt = kt + 1;
  1628.     }
  1629.   if (iop == 0)
  1630.     {
  1631.       if (kf != kingP[side] ||
  1632.       board[kf] != king ||
  1633.       board[rf] != rook ||
  1634.       color[kf] != side ||
  1635.       color[rf] != side ||
  1636.       Mvboard[kf] != 0 ||
  1637.       Mvboard[rf] != 0 ||
  1638.       color[kt] != neutral ||
  1639.       color[rt] != neutral ||
  1640.       color[kt - 1] != neutral ||
  1641.       SqAtakd3 (kf, xside) ||
  1642.       SqAtakd3 (kt, xside) ||
  1643.       SqAtakd3 (rt, xside))
  1644.     return (false);
  1645.     }
  1646.   else
  1647.     {
  1648.       if (iop == 1)
  1649.     {
  1650.       Castled[side] = 1;
  1651.       castld[side] = true;
  1652.       Mvboard[kf]++;
  1653.       Mvboard[rf]++;
  1654.     }
  1655.       else
  1656.     {
  1657.       Castled[side] = 0;
  1658.       castld[side] = false;
  1659.       Mvboard[kf]--;
  1660.       Mvboard[rf]--;
  1661.       t0 = kt;
  1662.       kt = kf;
  1663.       kf = t0;
  1664.       t0 = rt;
  1665.       rt = rf;
  1666.       rf = t0;
  1667.     }
  1668.       board[kt] = king;
  1669.       color[rt] = color[kt] = side;
  1670.       Pindex[kt] = 0;
  1671.       board[kf] = no_piece;
  1672.       color[rf] = color[kf] = neutral;
  1673.       board[rt] = rook;
  1674.       Pindex[rt] = Pindex[rf];
  1675.       board[rf] = no_piece;
  1676.       PieceList[side][Pindex[kt]] = kt;
  1677.       PieceList[side][Pindex[rt]] = rt;
  1678.       UpdateHashbd (side, king, kf, kt);
  1679.       UpdateHashbd (side, rook, rf, rt);
  1680.     }
  1681.   return (true);
  1682. }
  1683.  
  1684.  
  1685. void
  1686. EnPassant (short xside, short f, short t, short iop)
  1687.  
  1688. /*
  1689.  * Make or unmake an en passant move.
  1690.  */
  1691.  
  1692. {
  1693.   register short l;
  1694.  
  1695.   l = t + ((t > f) ? -8 : 8);
  1696.   if (iop == 1)
  1697.     {
  1698.       myEnPassant[xside] = 1;
  1699.       board[l] = no_piece;
  1700.       color[l] = neutral;
  1701.     }
  1702.   else
  1703.     {
  1704.       myEnPassant[xside] = 0;
  1705.       board[l] = pawn;
  1706.       color[l] = xside;
  1707.     }
  1708.   InitializeStats ();
  1709. }
  1710.  
  1711. void
  1712. UpdatePieceList (SHORT side, SHORT sq, SHORT iop,short piece)
  1713.  
  1714. /*
  1715.  * Update the PieceList and Pindex arrays when a piece is captured or when a
  1716.  * capture is unmade.
  1717.  */
  1718.  
  1719. {
  1720.   register SHORT i;
  1721.  
  1722.  if( iop == 1 ) {
  1723.    i = Pindex[ sq ];
  1724.    if( i < PieceCnt[ side ] ) {
  1725.      PieceList[ side ][ i ] = PieceList[ side ][ PieceCnt[ side ] ];
  1726.      Pindex[ PieceList[ side ][ i ] ] = i;
  1727.    }
  1728.    PieceCnt[ side ]--;    
  1729.  }
  1730.   else
  1731.     { if(piece != king){
  1732.       PieceCnt[side]++;
  1733.       PieceList[side][PieceCnt[side]] = sq;
  1734.       Pindex[sq] = PieceCnt[side];
  1735.       } else {
  1736.     PieceCnt[side]++;
  1737.     for (i = PieceCnt[side]; i > 0; i--)
  1738.         {
  1739.         PieceList[side][i] = PieceList[side][i - 1];
  1740.         Pindex[PieceList[side][i]] = i;
  1741.         } 
  1742.         PieceList[side][0] = sq;
  1743.         Pindex[sq] = 0;
  1744.  
  1745.       }
  1746.     }
  1747. }
  1748.  
  1749. void
  1750. MakeMove (SHORT side,
  1751.       struct leaf *node,
  1752.       SHORT *tempb, /* color of to square */
  1753.       SHORT *tempc, /* piece at to square */
  1754.       SHORT *tempsf,        /* static value of piece on from */
  1755.       SHORT *tempst,        /* static value of piece on to */
  1756.       SHORT *INCscore)      /* score increment for pawn structure change */
  1757.  
  1758. /*
  1759.  * Update Arrays board[], color[], and Pindex[] to reflect the new board
  1760.  * position obtained after making the move pointed to by node. Also update
  1761.  * miscellaneous stuff that changes when a move is made.
  1762.  */
  1763.  
  1764. {
  1765.   register SHORT f, t, xside, ct, cf;
  1766.   register struct GameRec *g;
  1767.  
  1768.   xside = side ^ 1;
  1769.   g = &GameList[++GameCnt];
  1770.   g->hashkey = hashkey;
  1771.   g->hashbd = hashbd;
  1772.   g->epssq = epsquare;
  1773.   f = node->f;
  1774.   t = node->t;
  1775.   epsquare = -1;
  1776.   /* FROMsquare = f;*/
  1777.   TOsquare = t;
  1778.   *INCscore = 0;
  1779.   g->Game50 = Game50;
  1780.   g->gmove = (f << 8) | t;
  1781.   g->flags = node->flags;
  1782.   if (node->flags & cstlmask)
  1783.     {
  1784.       g->piece = no_piece;
  1785.       g->color = side;
  1786.       (void) castle (side, f, t, 1);
  1787.       Game50 = GameCnt;
  1788.     }
  1789.   else
  1790.     {
  1791.       if (!(node->flags & capture) && (board[f] != pawn))
  1792.     { IncrementRPThash(side,hashkey); }
  1793.       else
  1794.     Game50 = GameCnt;
  1795.       *tempsf = svalue[f];
  1796.       *tempst = svalue[t];
  1797.       g->piece = *tempb = board[t];
  1798.       g->color = *tempc = color[t];
  1799.       if (*tempc != neutral)
  1800.     {
  1801.       UpdatePieceList (*tempc, t, 1,*tempb);
  1802.       /* if capture decrement pawn count */
  1803.       if (*tempb == pawn)
  1804.         {
  1805.           --PawnCnt[*tempc][column (t)];
  1806.         }
  1807.       if (board[f] == pawn)
  1808.         {
  1809.           cf = column (f);
  1810.           ct = column (t);
  1811.           /* move count from from to to */
  1812.           --PawnCnt[side][cf];
  1813.           ++PawnCnt[side][ct];
  1814.  
  1815.           /*
  1816.            * calculate increment for pawn structure
  1817.            * changes
  1818.            */
  1819.           /* doubled or more - */
  1820.           if (PawnCnt[side][ct] > (1 + PawnCnt[side][cf]))
  1821.         *INCscore -= 15;
  1822.           /* went to empty column + */
  1823.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1824.         *INCscore += 15;
  1825.  
  1826.           /*
  1827.            * went to outside col or empty col on one
  1828.            * side ????????
  1829.            */
  1830.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1831.         *INCscore -= 15;
  1832.         }
  1833.       mtl[xside] -= value[*tempb];
  1834.       if (*tempb == pawn)
  1835.         pmtl[xside] -= valueP;
  1836.       UpdateHashbd2 (xside, *tempb, -1, t);
  1837.       *INCscore += *tempst;
  1838.       Mvboard[t]++;
  1839.     }
  1840.       color[t] = color[f];
  1841.       board[t] = board[f];
  1842.       svalue[t] = svalue[f];
  1843.       Pindex[t] = Pindex[f];
  1844.       PieceList[side][Pindex[t]] = t;
  1845.       color[f] = neutral;
  1846.       board[f] = no_piece;
  1847.       if (board[t] == pawn)
  1848.     if (t - f == 16)
  1849.       epsquare = f + 8;
  1850.     else if (f - t == 16)
  1851.       epsquare = f - 8;
  1852.       if (node->flags & promote)
  1853.     {
  1854.       board[t] = node->flags & pmask;
  1855.       if (board[t] == queen)
  1856.         HasQueen[side]++;
  1857.       else if (board[t] == rook)
  1858.         HasRook[side]++;
  1859.       else if (board[t] == bishop)
  1860.         HasBishop[side]++;
  1861.       else if (board[t] == knight)
  1862.         HasKnight[side]++;
  1863.       --PawnCnt[side][column (t)];
  1864.       mtl[side] += value[board[t]] - valueP;
  1865.       pmtl[side] -= valueP;
  1866.       UpdateHashbd3 (side, pawn, f, -1);
  1867.       UpdateHashbd3 (side, board[t], f, -1);
  1868.       *INCscore -= *tempsf;
  1869.     }
  1870.       if (node->flags & epmask)
  1871.     EnPassant (xside, f, t, 1);
  1872.       else
  1873.     UpdateHashbd (side, board[t], f, t);
  1874.       Mvboard[f]++;
  1875.     }
  1876. }
  1877.  
  1878. void
  1879. UnmakeMove (SHORT side,
  1880.         struct leaf *node,
  1881.         SHORT *tempb, /* -> piece */
  1882.         SHORT *tempc, /* -> side */
  1883.         SHORT *tempsf,
  1884.         SHORT *tempst)
  1885.  
  1886. /*
  1887.  * Take back a move.
  1888.  */
  1889.  
  1890. {
  1891.   register SHORT f, t, xside;
  1892.  
  1893.   xside = side ^ 1;
  1894.   f = node->f;
  1895.   t = node->t;
  1896.   Game50 = GameList[GameCnt].Game50;
  1897.   if (node->flags & cstlmask)
  1898.     (void) castle (side, f, t, 2);
  1899.   else
  1900.     {
  1901.       color[f] = color[t];
  1902.       board[f] = board[t];
  1903.       svalue[f] = *tempsf;
  1904.       Pindex[f] = Pindex[t];
  1905.       PieceList[side][Pindex[f]] = f;
  1906.       color[t] = *tempc;
  1907.       board[t] = *tempb;
  1908.       svalue[t] = *tempst;
  1909.       if (node->flags & promote)
  1910.     {
  1911.       board[f] = pawn;
  1912.       ++PawnCnt[side][column (t)];
  1913.       mtl[side] += valueP - value[node->flags & pmask];
  1914.       pmtl[side] += valueP;
  1915.       UpdateHashbd2 (side, (SHORT) node->flags & pmask, -1, t);
  1916.       UpdateHashbd2 (side, pawn, -1, t);
  1917.     }
  1918.       if (*tempc != neutral)
  1919.     {
  1920.       UpdatePieceList (*tempc, t, 2,*tempb);
  1921.       if (*tempb == pawn)
  1922.         {
  1923.           ++PawnCnt[*tempc][column (t)];
  1924.         }
  1925.       if (board[f] == pawn)
  1926.         {
  1927.           --PawnCnt[side][column (t)];
  1928.           ++PawnCnt[side][column (f)];
  1929.         }
  1930.       mtl[xside] += value[*tempb];
  1931.       if (*tempb == pawn)
  1932.         pmtl[xside] += valueP;
  1933.       UpdateHashbd2 (xside, *tempb, -1, t);
  1934.       Mvboard[t]--;
  1935.     }
  1936.       if (node->flags & epmask)
  1937.     {
  1938.       EnPassant (xside, f, t, 2);
  1939.     }
  1940.       else
  1941.     UpdateHashbd (side, board[f], f, t);
  1942.       Mvboard[f]--;
  1943.       if (!(node->flags & capture) && (board[f] != pawn))
  1944.     { DecrementRPThash(side,hashkey); }
  1945.     }
  1946.   epsquare = GameList[GameCnt--].epssq;
  1947. }
  1948.  
  1949.  
  1950. void
  1951. InitializeStats (void)
  1952.  
  1953. /*
  1954.  * Scan thru the board seeing what's on each square. If a piece is found,
  1955.  * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1956.  * determine the material for each side and set the hashkey and hashbd
  1957.  * variables to represent the current board position. Array
  1958.  * PieceList[side][indx] contains the location of all the pieces of either
  1959.  * side. Array Pindex[sq] contains the indx into PieceList for a given
  1960.  * square.
  1961.  */
  1962.  
  1963. {
  1964.   register SHORT i, sq;
  1965.  
  1966.   epsquare = -1;
  1967.   for (i = 0; i < 8; i++)
  1968.     {
  1969.       PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1970.     }
  1971.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1972.   PieceCnt[white] = PieceCnt[black] = 0;
  1973.   hashbd = hashkey = 0;
  1974.   for (sq = 0; sq < 64; sq++)
  1975.     if (color[sq] != neutral)
  1976.       {
  1977.     mtl[color[sq]] += value[board[sq]];
  1978.     if (board[sq] == pawn)
  1979.       {
  1980.         pmtl[color[sq]] += valueP;
  1981.         ++PawnCnt[color[sq]][column (sq)];
  1982.       }
  1983.     Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
  1984.  
  1985.     PieceList[color[sq]][Pindex[sq]] = sq;
  1986.     UpdateHashbd2(color[sq], board[sq], -1, sq);
  1987.       }
  1988. }
  1989.