home *** CD-ROM | disk | FTP | other *** search
/ Dream 57 / Amiga_Dream_57.iso / Amiga / Jeux / Reflexion / Crafty-15.19.lha / crafty-15.19 / src / utility.c < prev    next >
C/C++ Source or Header  |  1998-09-21  |  70KB  |  2,187 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <ctype.h>
  7. #include "chess.h"
  8. #include "data.h"
  9. #if !defined(AMIGA)
  10. #  include <limits.h>
  11. #endif
  12. #if defined(OS2)
  13. #  include <sys/select.h>
  14. #endif
  15. #if defined(NT_i386) || defined(NT_AXP)
  16. #  include <windows.h>
  17. #  include <winbase.h>
  18. #  include <wincon.h>
  19. #  include <io.h>
  20. #  include <time.h>
  21. #else
  22. #  if !defined(MACOS)
  23. #    include <sys/times.h>
  24. #    include <sys/time.h>
  25. #  endif
  26. #endif
  27. #if defined(UNIX)
  28. #  include <unistd.h>
  29. #  include <sys/types.h>
  30. #  if !defined(LINUX) && !defined(ALPHA) && !defined(HP) && !defined(CRAY1) && !defined(FreeBSD) && !defined(__EMX__)
  31. #    if defined(AIX)
  32. #      include <sys/termio.h>
  33. #      include <sys/select.h>
  34. #    else
  35. #      if defined(NEXT)
  36. #        include <bsd/termios.h>
  37. #        include <sys/ioctl.h>
  38. #      else
  39. #        include <sys/filio.h>
  40. #      endif
  41. #    endif
  42. #    if !defined(NEXT)
  43. #      include <stropts.h>
  44. #    endif
  45. #    include <sys/conf.h>
  46. #  else
  47. #    include <sys/ioctl.h>
  48. #  endif
  49. #endif
  50. #if defined(UNIX)
  51. #  if !defined(CLK_TCK)
  52.      static clock_t clk_tck = 0;
  53. #  endif
  54. #endif
  55.  
  56. #if defined( AMIGA )
  57. #include <unistd.h>
  58. #include <fcntl.h>
  59. #endif
  60.  
  61. #if defined(__EMX__)
  62. #  define INCL_DOS
  63. #  define INCL_KBD
  64. #  include <os2.h>
  65. #endif
  66.  
  67. #if defined(MACOS)
  68. #  include <unistd.h>
  69. #  include <unix.h>
  70. #  include <Events.h>
  71.  
  72.    int CheckInput(void) {
  73.       EventRecord theEvent;
  74.  
  75.       return OSEventAvail(keyDownMask | autoKeyMask, &theEvent);
  76.    }
  77. #endif
  78.  
  79. # if defined(NT_i386) || defined(NT_AXP)
  80. #  include <windows.h>
  81. #  include <conio.h>
  82. int CheckInput(void)
  83. {
  84.   int i;
  85.    static int init = 0, pipe;
  86.    static HANDLE inh;
  87.    DWORD dw;
  88.  
  89.   if (!xboard && !ics && !isatty(fileno(stdin))) return(0);
  90.   if (batch_mode) return(0);
  91.   if (strchr(cmd_buffer,'\n')) return(1);
  92.   if (xboard) {
  93. #if defined(FILE_CNT)
  94.     if (stdin->_cnt > 0) return stdin->_cnt;
  95. #endif
  96.     if (!init) {
  97.       init = 1;
  98.       inh = GetStdHandle(STD_INPUT_HANDLE);
  99.       pipe = !GetConsoleMode(inh, &dw);
  100.       if (!pipe) {
  101.         SetConsoleMode(inh, dw & ~(ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT));
  102.         FlushConsoleInputBuffer(inh);
  103.       }
  104.     }
  105.     if (pipe) {
  106.       if (!PeekNamedPipe(inh, NULL, 0, NULL, &dw, NULL)) {
  107.         return 1;
  108.       }
  109.       return dw;
  110.     } else {
  111.       GetNumberOfConsoleInputEvents(inh, &dw);
  112.       return dw <= 1 ? 0 : dw;
  113.     }
  114.   }
  115.   else {
  116.     i=_kbhit();
  117.   }
  118.   return(i);
  119. }
  120. #endif
  121.  
  122. #if defined(DOS)
  123. int CheckInput(void)
  124. {
  125.   int i;
  126.   if (!xboard && !ics && !isatty(fileno(stdin))) return(0);
  127.   if (batch_mode) return(0);
  128.   if (strchr(cmd_buffer,'\n')) return(1);
  129.   i=bioskey(1);
  130.   return(i);
  131. }
  132. #endif
  133.  
  134. #if defined(UNIX) || defined(AMIGA)
  135. #  ifdef __EMX__
  136. int CheckInput(void) {
  137.   static KBDKEYINFO keyinfo;
  138.   int i;
  139.  
  140.   if (!xboard && !ics && !isatty(fileno(stdin))) return(0);
  141.   if (strchr(cmd_buffer,'\n')) return(1);
  142.   KbdPeek (&keyinfo, 0);
  143.   if (keyinfo.fbStatus & KBDTRF_FINAL_CHAR_IN) i = 1;
  144.   else i = 0;
  145.   return(i);
  146. }
  147. #else
  148. int CheckInput(void) {
  149.   fd_set readfds;
  150.   struct timeval tv;
  151.   int data;
  152.  
  153.   if (!xboard && !ics && !isatty(fileno(stdin))) return(0);
  154.   if (batch_mode) return(0);
  155.   if (strchr(cmd_buffer,'\n')) return(1);
  156.   FD_ZERO (&readfds);
  157.   FD_SET (fileno(stdin), &readfds);
  158.   tv.tv_sec=0;
  159.   tv.tv_usec=0;
  160.   select(16, &readfds, 0, 0, &tv);
  161.   data=FD_ISSET(fileno(stdin), &readfds);
  162.   return(data);
  163. }
  164. #  endif
  165. #endif
  166.  
  167. void Delay232(int ms)
  168. {
  169.   int old,new;
  170.   old=ReadClock(elapsed);
  171.   do {
  172.     new=ReadClock(elapsed);
  173.   } while (new-ms/10 < old);
  174. }
  175.  
  176. void ClearHashTables(void)
  177. {
  178.   int i;
  179.  
  180.   if (trans_ref_ba && trans_ref_wa) {
  181.     for (i=0;i<hash_table_size;i++) {
  182.       (trans_ref_ba+i)->word1=Or(And((trans_ref_ba+i)->word1,
  183.                   mask_clear_entry),Shiftl((BITBOARD) 65536,21));
  184.           (trans_ref_wa+i)->word1=Or(And((trans_ref_wa+i)->word1,
  185.                   mask_clear_entry),Shiftl((BITBOARD) 65536,21));
  186.     }
  187.     for (i=0;i<2*hash_table_size;i++) {
  188.       (trans_ref_bb+i)->word1=Or(And((trans_ref_bb+i)->word1,
  189.                       mask_clear_entry),Shiftl((BITBOARD) 65536,21));
  190.       (trans_ref_wb+i)->word1=Or(And((trans_ref_wb+i)->word1,
  191.                       mask_clear_entry),Shiftl((BITBOARD) 65536,21));
  192.     }
  193.   }
  194. }
  195.  
  196. void DisplayBitBoard(BITBOARD board)
  197. {
  198.   union doub {
  199.     char i[8];
  200.     BITBOARD d;
  201.   };
  202.   union doub x;
  203.   int i,j;
  204. #if defined(LITTLE_ENDIAN_ARCH) && defined(HAS_LONGLONG)
  205.   int subs[8]={7,6,5,4,3,2,1,0};
  206. #endif
  207. #if defined(LITTLE_ENDIAN_ARCH) && !defined(HAS_LONGLONG)
  208.   int subs[8]={3,2,1,0,7,6,5,4};
  209. #endif
  210.  
  211.   x.d=board;
  212. #if defined(LITTLE_ENDIAN_ARCH)
  213.   for(i=7;i>=0;i--) {
  214.     printf("  %2d ",i*8);
  215.     for(j=128;j>0;j=j>>1)
  216.       if(x.i[subs[i]] & j)
  217.         printf("X ");
  218.       else
  219.         printf("- ");
  220.     printf("\n");
  221.   }
  222. #else
  223.   for(i=7;i>=0;i--) {
  224.     printf("  %2d ",i*8);
  225.     for(j=128;j>0;j=j>>1)
  226.       if(x.i[i] & j)
  227.         printf("X ");
  228.       else
  229.         printf("- ");
  230.     printf("\n");
  231.   }
  232. #endif
  233. }
  234.  
  235. /*
  236. ********************************************************************************
  237. *                                                                              *
  238. *   DisplayChessBoard() is used to display the board since it is kept in       *
  239. *   both the bit-board and array formats, here we use the array format which   *
  240. *   is nearly ready for display as is.                                         *
  241. *                                                                              *
  242. ********************************************************************************
  243. */
  244. void DisplayChessBoard(FILE *display_file, POSITION pos)
  245. {
  246.   int display_board[64];
  247.   char display_string[] =
  248.     {"*Q\0*R\0*B\0  \0*K\0*N\0*P\0  \0P \0N \0K \0  \0B \0R \0Q \0"};
  249.   int i,j;
  250. /*
  251.  ----------------------------------------------------------
  252. |                                                          |
  253. |   first, convert square values to indices to the proper  |
  254. |   text string.                                           |
  255. |                                                          |
  256.  ----------------------------------------------------------
  257. */
  258.   for(i=0;i<64;i++) display_board[i]=(pos.board[i]+7)*3;
  259. /*
  260.  ----------------------------------------------------------
  261. |                                                          |
  262. |   now that that's done, simply display using 8 squares   |
  263. |   per line.                                              |
  264. |                                                          |
  265.  ----------------------------------------------------------
  266. */
  267.   fprintf(display_file,"\n       +---+---+---+---+---+---+---+---+\n");
  268.   for(i=7;i>=0;i--) {
  269.     fprintf(display_file,"   %2d  ",i+1);
  270.     for(j=0;j<8;j++)
  271.       fprintf(display_file,"| %s",&display_string[display_board[i*8+j]]);
  272.     fprintf(display_file,"|\n");
  273.     fprintf(display_file,"       +---+---+---+---+---+---+---+---+\n");
  274.   }
  275.   fprintf(display_file,"         a   b   c   d   e   f   g   h\n\n");
  276. }
  277.  
  278. char* DisplayEvaluation(int value)
  279. {
  280.   static char out[10];
  281.  
  282.   if (abs(value) < MATE-100)
  283.     sprintf(out,"%7.2f",((float) value)/100.0);
  284.   else if (abs(value) > MATE) {
  285.     if (value < 0) sprintf(out," -infnty");
  286.     else sprintf(out," +infnty");
  287.   }
  288.   else if (value == MATE-2) sprintf(out,"   Mate");
  289.   else if (value == -(MATE-1)) sprintf(out,"  -Mate");
  290.   else if (value > 0) sprintf(out,"  Mat%.2d",(MATE-value)/2);
  291.   else sprintf(out," -Mat%.2d",(MATE-abs(value))/2);
  292.   return(out);
  293. }
  294.  
  295. char* DisplayEvaluationWhisper(int value)
  296. {
  297.   static char out[10];
  298.  
  299.   if (abs(value) < MATE-100)
  300.     sprintf(out,"%+.2f",((float) value)/100.0);
  301.   else if (abs(value) > MATE) {
  302.     if (value < 0) sprintf(out,"-infnty");
  303.     else sprintf(out,"+infnty");
  304.   }
  305.   else if (value == MATE-2) sprintf(out,"Mate");
  306.   else if (value == -(MATE-1)) sprintf(out,"-Mate");
  307.   else if (value > 0) sprintf(out,"Mat%.2d",(MATE-value)/2);
  308.   else sprintf(out,"-Mat%.2d",(MATE-abs(value))/2);
  309.   return(out);
  310. }
  311.  
  312. void DisplayPieceBoards(int *white, int *black)
  313. {
  314.   int i,j;
  315.   printf("                 white                      ");
  316.   printf("                 black\n");
  317.   for (i=7;i>=0;i--) {
  318.     for (j=i*8;j<i*8+8;j++) printf("%4d ",white[j]);
  319.     printf("    ");
  320.     for (j=i*8;j<i*8+8;j++) printf("%4d ",black[j]);
  321.     printf("\n");
  322.   }
  323. }
  324.  
  325. /* last modified 08/23/96 */
  326. /*
  327. ********************************************************************************
  328. *                                                                              *
  329. *   DisplayPV() is used to display a PV during the search.  it will also note  *
  330. *   when the PV was terminated by a hash table hit and will check the hash     *
  331. *   entries to see if the PV can be extended by using moves from hits.         *
  332. *                                                                              *
  333. ********************************************************************************
  334. */
  335. void DisplayPV(TREE *tree, int level, int wtm, int time, int value, PATH *pv) {
  336. #define PrintOK() (tree->nodes_searched>noise_level || value>(MATE-100))
  337.   char buffer[512], *buffp, *bufftemp;
  338.   int i, t_move_number, type, j, dummy;
  339. /*
  340.  ----------------------------------------------------------
  341. |                                                          |
  342. |   initialize.                                            |
  343. |                                                          |
  344.  ----------------------------------------------------------
  345. */
  346.   if (level==5) type=4; else type=2;
  347.   t_move_number=move_number;
  348.   if (display_options&64) sprintf(buffer," %d.",move_number);
  349.   else buffer[0]=0;
  350.   if ((display_options&64) && !wtm) sprintf(buffer+strlen(buffer)," ...");
  351.   for (i=1;i<=(int) pv->path_length;i++) {
  352.     if ((display_options&64) && i>1 && wtm)
  353.       sprintf(buffer+strlen(buffer)," %d.",t_move_number);
  354.     sprintf(buffer+strlen(buffer)," %s",OutputMove(tree,pv->path[i],i,wtm));
  355.     MakeMove(tree,i,pv->path[i],wtm);
  356.     wtm=ChangeSide(wtm);
  357.     if (wtm) t_move_number++;
  358.   }
  359. /*
  360.  ----------------------------------------------------------
  361. |                                                          |
  362. |   if the pv was terminated prematurely by a trans/ref    |
  363. |   hit, see if any more moves are in the trans/ref table  |
  364. |   and if so, add 'em to the end of the PV so we will     |
  365. |   have better move ordering next iteration.              |
  366. |                                                          |
  367.  ----------------------------------------------------------
  368. */
  369.   if(pv->path_hashed == 1) {
  370.     for (i=pv->path_length+1;i<MAXPLY;i++) {
  371.       LookUp(tree,i,0,wtm,&dummy,&dummy,&dummy);
  372.       if (tree->hash_move[i] && LegalMove(tree,i,wtm,tree->hash_move[i])) {
  373.         pv->path[i]=tree->hash_move[i];
  374.         for (j=1;j<i;j++)
  375.           if (pv->path[i] == pv->path[j]) break;
  376.         if (j < i) break;
  377.         pv->path_length++;
  378.         if ((display_options&64) && wtm)
  379.           sprintf(buffer+strlen(buffer)," %d.",t_move_number);
  380.         sprintf(buffer+strlen(buffer)," %s",OutputMove(tree,pv->path[i],i,wtm));
  381.         MakeMove(tree,i,pv->path[i],wtm);
  382.       }
  383.       else break;
  384.       wtm=ChangeSide(wtm);
  385.       if (wtm) t_move_number++;
  386.     }
  387.     sprintf(buffer+strlen(buffer)," <HT>");
  388.   }
  389.   else if(pv->path_hashed == 2)
  390.     sprintf(buffer+strlen(buffer)," <EGTB>");
  391.   strcpy(whisper_text,buffer);
  392.   if (PrintOK()) {
  393.     if (level==6)
  394.       Print(type,"               %2i   %s%s   ",iteration_depth,
  395.             DisplayTime(time),DisplayEvaluation(value));
  396.     else
  397.       Print(type,"               %2i-> %s%s   ",iteration_depth,
  398.             DisplayTime(time),DisplayEvaluation(value));
  399.     buffp=buffer+1;
  400.     do {
  401.       if ((int) strlen(buffp) > 34)
  402.         bufftemp=strchr(buffp+34,' ');
  403.       else
  404.         bufftemp=0;
  405.       if (bufftemp) *bufftemp=0;
  406.       Print(type,"%s\n",buffp);
  407.       buffp=bufftemp+1;
  408.       if (bufftemp) Print(type,"                                    ");
  409.     } while(bufftemp);
  410.     Whisper(level,iteration_depth,end_time-start_time,whisper_value,
  411.             tree->nodes_searched,0,whisper_text);
  412.   }
  413.   for (i=pv->path_length;i>0;i--) {
  414.     wtm=ChangeSide(wtm);
  415.     UnMakeMove(tree,i,pv->path[i],wtm);
  416.   }
  417. }
  418.  
  419. char* DisplaySQ(unsigned int sq)
  420. {
  421.   static char out[3];
  422.   out[0]=(From(sq) & 7)+'a';
  423.   out[1]=(From(sq) / 8)+'1';
  424.   out[2]=0;
  425.   return(out);
  426. }
  427.  
  428. char* DisplayHHMM(unsigned int time)
  429. {
  430.   static char out[10];
  431.  
  432.   time=time/6000;
  433.   sprintf(out,"%3u:%02u", time/60, time%60);
  434.   return(out);
  435. }
  436.  
  437. char* DisplayTime(unsigned int time)
  438. {
  439.   static char out[10];
  440.  
  441.   if (time < 6000) sprintf(out,"%6.2f",(float) time/100.0);
  442.   else {
  443.     time=time/100;
  444.     sprintf(out,"%3u:%02u", time/60, time%60);
  445.   }
  446.   return(out);
  447. }
  448.  
  449. char* DisplayTimeWhisper(unsigned int time) {
  450.   static char out[10];
  451.  
  452.   if (time < 6000) sprintf(out,"%.2f",(float) time/100.0);
  453.   else {
  454.     time=time/100;
  455.     sprintf(out,"%u:%02u", time/60, time%60);
  456.   }
  457.   return(out);
  458. }
  459.  
  460. void DisplayTreeState(TREE *tree, int sply, int spos, int maxply) {
  461.   int left, i, *mvp, parallel=0;
  462.   char buf[1024];
  463.   buf[0]=0;
  464.   if (sply == 1) {
  465.     for (left=0,mvp=tree->last[0];mvp<tree->last[1];mvp++)
  466.       if (!tree->searched_this_root_move[mvp-tree->last[0]]) left++;
  467.     sprintf(buf,"%d:%d/%d  ",1,left,tree->last[1]-tree->last[0]);
  468.   }
  469.   else {
  470.     for (i=0;i<spos-6;i++) sprintf(buf+strlen(buf)," ");
  471.     sprintf(buf+strlen(buf),"[p%2d] ",tree->thread_id);
  472.   }
  473.   for (i=Max(sply,2);i<=maxply;i++) {
  474.     left=0;
  475.     for (mvp=tree->last[i-1];mvp<tree->last[i];mvp++)
  476.       if (*mvp) left++;
  477.     sprintf(buf+strlen(buf),"%d:%d/%d  ",i,left,tree->last[i]-tree->last[i-1]);
  478.     if (!(i%8)) sprintf(buf+strlen(buf),"\n");
  479.     if (tree->nprocs>1 && tree->ply==i) {
  480.       parallel=strlen(buf);
  481.       break;
  482.     }
  483.     if (sply > 1) break;
  484.   }
  485.   printf("%s\n",buf);
  486.   if (sply == 1 && tree->nprocs) {
  487.     for (i=0;i<max_threads;i++) if (tree->siblings[i])
  488.         DisplayTreeState(tree->siblings[i], tree->ply+1,parallel, maxply);
  489.   }
  490. }
  491.  
  492. void Display64bitWord(BITBOARD word)
  493. {
  494.   union doub {
  495.     unsigned int i[2];
  496.     BITBOARD d;
  497.   };
  498.   union doub x;
  499.   x.d=word;
  500. #if defined(LITTLE_ENDIAN_ARCH)
  501.   printf("%08x%08x\n",x.i[1],x.i[0]);
  502. #else
  503.   printf("%08x%08x\n",x.i[0],x.i[1]);
  504. #endif
  505. }
  506.  
  507. void Display2BitBoards(BITBOARD board1, BITBOARD board2)
  508. {
  509.   union doub {
  510.     char i[8];
  511.     BITBOARD d;
  512.   };
  513.   union doub x,y;
  514.   int i,j;
  515. #if defined(LITTLE_ENDIAN_ARCH) && defined(HAS_LONGLONG)
  516.   int subs[8]={7,6,5,4,3,2,1,0};
  517. #endif
  518. #if defined(LITTLE_ENDIAN_ARCH) && !defined(HAS_LONGLONG)
  519.   int subs[8]={3,2,1,0,7,6,5,4};
  520. #endif
  521.  
  522.   x.d=board1;
  523.   y.d=board2;
  524.   printf("          good                     bad\n");
  525. #if defined(LITTLE_ENDIAN_ARCH)
  526.   for(i=7;i>=0;i--) {
  527.     printf("  %2d ",i*8);
  528.     for(j=128;j>0;j=j>>1)
  529.       if(x.i[subs[i]] & j) printf("X ");
  530.       else printf("- ");
  531.     printf("     %2d ",i*8);
  532.     for(j=128;j>0;j=j>>1)
  533.       if(y.i[subs[i]] & j) printf("X ");
  534.       else printf("- ");
  535.     printf("\n");
  536.   }
  537. #else
  538.   for(i=7;i>=0;i--) {
  539.     printf("  %2d ",i*8);
  540.     for(j=128;j>0;j=j>>1)
  541.       if(x.i[i] & j) printf("X ");
  542.       else printf("- ");
  543.     printf("     %2d ",i*8);
  544.     for(j=128;j>0;j=j>>1)
  545.       if(y.i[i] & j) printf("X ");
  546.       else printf("- ");
  547.     printf("\n");
  548.   }
  549. #endif
  550. }
  551.  
  552. void DisplayChessMove(char *title, int move)
  553. {
  554.   Print(4095,"%s  piece=%d, from=%d, to=%d, captured=%d, promote=%d\n",
  555.          title,Piece(move),From(move), To(move),Captured(move),
  556.          Promote(move));
  557. }
  558.  
  559. /* last modified 02/17/98 */
  560. /*
  561. ********************************************************************************
  562. *                                                                              *
  563. *   FormatPV() is used to display a PV during the search.  it will also note   *
  564. *   when the PV was terminated by a hash table hit.                            *
  565. *                                                                              *
  566. ********************************************************************************
  567. */
  568. char *FormatPV(TREE *tree, int wtm, PATH pv) {
  569. #define PrintOK() (tree->nodes_searched>noise_level || value>(MATE-100))
  570.   static char buffer[512];
  571.   int i, t_move_number;
  572. /*
  573.  ----------------------------------------------------------
  574. |                                                          |
  575. |   initialize.                                            |
  576. |                                                          |
  577.  ----------------------------------------------------------
  578. */
  579.   t_move_number=move_number;
  580.   if (display_options&64) sprintf(buffer," %d.",move_number);
  581.   else buffer[0]=0;
  582.   if ((display_options&64) && !wtm) sprintf(buffer+strlen(buffer)," ...");
  583.   for (i=1;i<=(int) pv.path_length;i++) {
  584.     if ((display_options&64) && i>1 && wtm)
  585.       sprintf(buffer+strlen(buffer)," %d.",t_move_number);
  586.     sprintf(buffer+strlen(buffer)," %s",OutputMove(tree,pv.path[i],i,wtm));
  587.     MakeMove(tree,i,pv.path[i],wtm);
  588.     wtm=ChangeSide(wtm);
  589.     if (wtm) t_move_number++;
  590.   }
  591.   for (i=pv.path_length;i>0;i--) {
  592.     wtm=ChangeSide(wtm);
  593.     UnMakeMove(tree,i,pv.path[i],wtm);
  594.   }
  595.   return (buffer);
  596. }
  597.  
  598. #if defined(MACOS)
  599. unsigned int ReadClock(TIME_TYPE type)
  600. {
  601.       return(clock() * 100 / CLOCKS_PER_SEC);
  602. }
  603. #else
  604. unsigned int ReadClock(TIME_TYPE type)
  605. {
  606. #if defined(UNIX) || defined(AMIGA)
  607.   struct tms t;
  608.   struct timeval timeval;
  609.   struct timezone timezone;
  610.   BITBOARD cputime=0;
  611. #endif
  612.  
  613.   switch (type) {
  614. #if defined(UNIX) || defined(AMIGA)
  615.     case cpu:
  616.       (void) times(&t);
  617.       cputime=t.tms_utime+t.tms_stime+t.tms_cutime+t.tms_cstime;
  618. #  if defined(CLK_TCK)
  619.       cputime=cputime*100/CLK_TCK;
  620.       return((unsigned int) cputime);
  621. #  else
  622.       if (!clk_tck) clk_tck = sysconf(_SC_CLK_TCK);
  623.       cputime=cputime*100/clk_tck;
  624.       return((unsigned int) cputime);
  625. #  endif
  626.     case elapsed:
  627.       gettimeofday(&timeval, &timezone);
  628.       return(timeval.tv_sec*100+(timeval.tv_usec/10000));
  629.     default:
  630.       gettimeofday(&timeval, &timezone);
  631.       return(timeval.tv_sec*100+(timeval.tv_usec/10000));
  632. #endif
  633. #if defined(NT_i386) || defined(NT_AXP)
  634.     case cpu:
  635.       return(clock()/(CLOCKS_PER_SEC/100));
  636.     case elapsed:
  637.       return( (unsigned int) GetTickCount()/10);
  638.     default:
  639.       return( (unsigned int) GetTickCount()/10);
  640. #endif
  641. #if defined(DOS)
  642.     case elapsed:
  643.       return(time(0)*100);
  644.     default:
  645.       return(time(0)*100);
  646. #endif
  647.   }
  648. }
  649. #endif
  650.  
  651. #if defined(SMP)
  652. /*
  653. ********************************************************************************
  654. *                                                                              *
  655. *   FindBlockID() converts a thread block pointer into an ID that is easier to *
  656. *   understand when debugging.                                                 *
  657. *                                                                              *
  658. ********************************************************************************
  659. */
  660. int FindBlockID(TREE *block) {
  661.   int i;
  662.   for (i=0;i<MAX_BLOCKS+1;i++)
  663.     if (block == local[i]) return(i);
  664.   return(-1);
  665. }
  666. #endif
  667.  
  668. /*
  669. ********************************************************************************
  670. *                                                                              *
  671. *   HasOpposition() is used to determine if one king stands in "opposition"    *
  672. *   to the other.  if the kings are opposed on the same file or else are       *
  673. *   opposed on the same diagonal, then the side not-to-move has the opposition *
  674. *   and the side-to-move must give way.                                        *
  675. *                                                                              *
  676. ********************************************************************************
  677. */
  678. int HasOpposition(int on_move, int white_king, int black_king)
  679. {
  680.   register int file_distance, rank_distance;
  681.   file_distance=FileDistance(white_king,black_king);
  682.   rank_distance=RankDistance(white_king,black_king);
  683.   if (rank_distance < 2) return(1);
  684.   if (on_move) {
  685.     if (rank_distance > 2) rank_distance--;
  686.     else file_distance--;
  687.   }
  688.   if ((file_distance == 2) && (rank_distance == 2)) return(1);
  689.   if ((file_distance == 0) && (rank_distance == 2)) return(1);
  690.   return(0);
  691. }
  692.  
  693. /*
  694. ********************************************************************************
  695. *                                                                              *
  696. *   InterposeSquares() is used to compute the set of squares that block an     *
  697. *   attack on the king by a sliding piece, by interposing any piece between    *
  698. *   the attacking piece and the king on the same ray.                          *
  699. *                                                                              *
  700. ********************************************************************************
  701. */
  702. BITBOARD InterposeSquares(int check_direction, int king_square,
  703.                           int checking_square)
  704. {
  705.   register BITBOARD target;
  706. /*
  707.  ----------------------------------------------------------
  708. |                                                          |
  709. |   if this is a check from a single sliding piece, then   |
  710. |   we can interpose along the checking rank/file/diagonal |
  711. |   and block the check.  otherwise, interposing is not a  |
  712. |   possibility.                                           |
  713. |                                                          |
  714.  ----------------------------------------------------------
  715. */
  716.   switch (check_direction) {
  717.     case +1:
  718.       target=Xor(plus1dir[king_square-1],plus1dir[checking_square]);
  719.       break;
  720.     case +7:
  721.       target=Xor(plus7dir[king_square-7],plus7dir[checking_square]);
  722.       break;
  723.     case +8:
  724.       target=Xor(plus8dir[king_square-8],plus8dir[checking_square]);
  725.       break;
  726.     case +9:
  727.       target=Xor(plus9dir[king_square-9],plus9dir[checking_square]);
  728.       break;
  729.     case -1:
  730.       target=Xor(minus1dir[king_square+1],minus1dir[checking_square]);
  731.       break;
  732.     case -7:
  733.       target=Xor(minus7dir[king_square+7],minus7dir[checking_square]);
  734.       break;
  735.     case -8:
  736.       target=Xor(minus8dir[king_square+8],minus8dir[checking_square]);
  737.       break;
  738.     case -9:
  739.       target=Xor(minus9dir[king_square+9],minus9dir[checking_square]);
  740.       break;
  741.     default:
  742.       target=0;
  743.       break;
  744.   }
  745.   return(target);
  746. }
  747.  
  748. int KingPawnSquare(int pawn, int king, int queen, int ptm)
  749. {
  750.   register int pdist, kdist;
  751.   pdist=abs((pawn>>3)-(queen>>3));
  752.   kdist=(abs((king>>3)-(queen>>3)) > abs((king&7)-(queen&7))) ?
  753.     abs((king>>3)-(queen>>3)) : abs((king&7)-(queen&7));
  754.   if (!ptm) pdist++;
  755.   if (pdist < kdist) return(0);
  756.   else return(1);
  757. }
  758.  
  759. /* last modified 05/01/97 */
  760. /*
  761. ********************************************************************************
  762. *                                                                              *
  763. *   NewGame() is used to initialize the chess position and timing controls to  *
  764. *   the setup needed to start a new game.                                      *
  765. *                                                                              *
  766. ********************************************************************************
  767. */
  768. void NewGame(int save) {
  769.   char filename[64];
  770.   static int save_book_selection_width=5;
  771.   static int save_whisper=0, save_kibitz=0, save_channel=0;
  772.   static int save_resign=0, save_resign_count=0, save_draw_count=0;
  773.   static int save_learning=0;
  774.   static int save_accept_draws=0;
  775.   TREE *tree=local[0];
  776.  
  777.   new_game=0;
  778.   if (save) {
  779.     save_book_selection_width=book_selection_width;
  780.     save_whisper=whisper;
  781.     save_kibitz=kibitz;
  782.     save_channel=channel;
  783.     save_resign=resign;
  784.     save_resign_count=resign_count;
  785.     save_draw_count=draw_count;
  786.     save_learning=learning;
  787.     save_accept_draws=accept_draws;
  788.   }
  789.   else {
  790.     if (learning&book_learning && moves_out_of_book)
  791.       LearnBook(tree,crafty_is_white,last_search_value,0,0,1);
  792.     if (ics) printf("*whisper Hello from Crafty v%s !\n",version);
  793.     if (xboard) {
  794. #if defined(SMP)
  795.       printf("kibitz Hello from Crafty v%s! (%d cpus)\n",version,CPUS);
  796. #else
  797.       printf("kibitz Hello from Crafty v%s!\n",version);
  798. #endif
  799.     }
  800.     over=0;
  801.     moves_out_of_book=0;
  802.     ponder_move=0;
  803.     previous_search_value=0;
  804.     last_pv.path_iteration_depth=0;
  805.     last_pv.path_length=0;
  806.     strcpy(initial_position,"");
  807.     InitializeChessBoard(&tree->position[0]);
  808.     InitializeHashTables();
  809.     force=0;
  810.     no_tricks=1;
  811.     computer_opponent=0;
  812.     default_draw_score=0;
  813.     wtm=1;
  814.     move_number=1;
  815.     tc_time_remaining=tc_time;
  816.     tc_time_remaining_opponent=tc_time;
  817.     tc_moves_remaining=tc_moves;
  818.     if (log_file) fclose(log_file);
  819.     if (history_file) fclose(history_file);
  820.     if (log_file) {
  821.       log_id++;
  822. #if defined(MACOS)
  823.       sprintf(filename,":%s:log.%03d",log_path,log_id);
  824. #else
  825.       sprintf(filename,"%s/log.%03d",log_path,log_id);
  826. #endif
  827.       log_file=fopen(filename,"w+");
  828.     }
  829. #if defined(MACOS)
  830.     sprintf(filename,":%s:game.%03d",log_path,log_id);
  831. #else
  832.     sprintf(filename,"%s/game.%03d",log_path,log_id);
  833. #endif
  834.     history_file=fopen(filename,"w+");
  835.     book_selection_width=save_book_selection_width;
  836.     whisper=save_whisper;
  837.     kibitz=save_kibitz;
  838.     channel=save_channel;
  839.     resign=save_resign;
  840.     resign_count=save_resign_count;
  841.     resign_counter=0;
  842.     draw_count=save_draw_count;
  843.     accept_draws=save_accept_draws;
  844.     draw_counter=0;
  845.     usage_level=0;
  846.     learning=save_learning;
  847.     largest_positional_score=100;
  848.     predicted=0;
  849.     whisper_depth=0;
  850.     whisper_value=0;
  851.     tree->nodes_searched=0;
  852.     tree->fail_high=0;
  853.     tree->fail_high_first=0;
  854.     cpu_percent=0;
  855.     whisper_text[0]=0;
  856.   }
  857. }
  858.  
  859. char* Normal(void)
  860. {
  861. #if defined(NT_i386) || defined(NT_AXP)
  862.   HANDLE  std_console;
  863.   std_console = GetStdHandle(STD_OUTPUT_HANDLE);
  864. #endif
  865.  
  866.   if (ansi) {
  867. #if defined(UNIX) || defined(AMIGA)
  868.     return("\033[0m");
  869. #elif defined(NT_i386) || defined(NT_AXP)
  870.     SetConsoleTextAttribute(std_console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
  871.     return("");
  872. #else
  873.     return("\033[1;44;37m");
  874. #endif
  875.   }
  876.   return("");
  877. }
  878.  
  879. int ParseTime(char* string)
  880. {
  881.   int time=0;
  882.   int minutes=0;
  883.   while (*string) {
  884.     switch (*string) {
  885.       case '0':
  886.       case '1':
  887.       case '2':
  888.       case '3':
  889.       case '4':
  890.       case '5':
  891.       case '6':
  892.       case '7':
  893.       case '8':
  894.       case '9':
  895.         minutes=minutes*10+(*string)-'0';
  896.         break;
  897.       case ':':
  898.         time=time*60+minutes;
  899.         minutes=0;
  900.         break;
  901.       default: Print(4095,"illegal character in time, please re-enter\n");
  902.         break;
  903.     }
  904.     string++;
  905.   }
  906.   return(time*60+minutes);
  907. }
  908.  
  909. void Pass(void) {
  910.   char buffer[128];
  911.   int halfmoves_done=2*(move_number-1)+(1-wtm);
  912.   int prev_pass=0;
  913.   /* Was previous move a pass? */
  914.   if (halfmoves_done>0) {
  915.     fseek(history_file,(halfmoves_done-1)*10,SEEK_SET);
  916.     if (fscanf(history_file,"%s",buffer)==0 || strcmp(buffer,"pass")==0) {
  917.       prev_pass=1;
  918.     }
  919.   }
  920.   if (prev_pass) {
  921.     if (wtm) move_number--;
  922.   } else {
  923.     fseek(history_file,halfmoves_done*10,SEEK_SET);
  924.     fprintf(history_file,"%9s\n","pass");
  925.     if (!wtm) move_number++;
  926.   }
  927.   wtm=ChangeSide(wtm);
  928. }
  929.  
  930.  
  931. /*
  932. ********************************************************************************
  933. *                                                                              *
  934. *   PinnedOnKing() is used to determine if the piece on <square> is pinned     *
  935. *   against the king, so that it's illegal to move it.  this is used to screen *
  936. *   potential moves by GenerateCheckEvasions() so that illegal moves are not   *
  937. *   produced.                                                                  *
  938. *                                                                              *
  939. ********************************************************************************
  940. */
  941. int PinnedOnKing(TREE *tree, int wtm, int square)
  942. {
  943.   register int ray;
  944.   if (wtm) {
  945. /*
  946.  ----------------------------------------------------------
  947. |                                                          |
  948. |   first, determine if the piece being moved is on the    |
  949. |   same diagonal, rank or file as the king.               |
  950. |                                                          |
  951.  ----------------------------------------------------------
  952. */
  953.     ray=directions[square][WhiteKingSQ];
  954.     if (!ray) return(0);
  955. /*
  956.  ----------------------------------------------------------
  957. |                                                          |
  958. |   if they are on the same ray, then determine if the     |
  959. |   king blocks a bishop attack in one direction from this |
  960. |   square and a bishop or queen blocks a bishop attack    |
  961. |   on the same diagonal in the opposite direction.        |
  962. |                                                          |
  963.  ----------------------------------------------------------
  964. */
  965.     switch (abs(ray)) {
  966.     case 1:
  967.       if (And(AttacksRank(square),WhiteKing) != 0)
  968.         return(And(And(AttacksRank(square),RooksQueens),
  969.                    BlackPieces) != 0);
  970.       else return(0);
  971.     case 7:
  972.       if (And(AttacksDiaga1(square),WhiteKing) != 0)
  973.         return(And(And(AttacksDiaga1(square),BishopsQueens),
  974.                    BlackPieces) != 0);
  975.       else return(0);
  976.     case 8:
  977.       if (And(AttacksFile(square),WhiteKing) != 0)
  978.         return(And(And(AttacksFile(square),RooksQueens),
  979.                    BlackPieces) != 0);
  980.       else return(0);
  981.     case 9:
  982.       if (And(AttacksDiagh1(square),WhiteKing) != 0)
  983.         return(And(And(AttacksDiagh1(square),BishopsQueens),
  984.                    BlackPieces) != 0);
  985.       else return(0);
  986.     }
  987.   }
  988.   else {
  989. /*
  990.  ----------------------------------------------------------
  991. |                                                          |
  992. |   first, determine if the piece being moved is on the    |
  993. |   same diagonal, rank or file as the king.               |
  994. |                                                          |
  995.  ----------------------------------------------------------
  996. */
  997.     ray=directions[BlackKingSQ][square];
  998.     if (!ray) return(0);
  999. /*
  1000.  ----------------------------------------------------------
  1001. |                                                          |
  1002. |   if they are on the same ray, then determine if the     |
  1003. |   king blocks a bishop attack in one direction from this |
  1004. |   square and a bishop or queen blocks a bishop attack    |
  1005. |   on the same diagonal in the opposite direction.        |
  1006. |                                                          |
  1007.  ----------------------------------------------------------
  1008. */
  1009.     switch (abs(ray)) {
  1010.     case 1:
  1011.       if (And(AttacksRank(square),BlackKing) != 0)
  1012.         return(And(And(AttacksRank(square),RooksQueens),
  1013.                    WhitePieces) != 0);
  1014.       else return(0);
  1015.     case 7:
  1016.       if (And(AttacksDiaga1(square),BlackKing) != 0)
  1017.         return(And(And(AttacksDiaga1(square),BishopsQueens),
  1018.                    WhitePieces) != 0);
  1019.       else return(0);
  1020.     case 8:
  1021.       if (And(AttacksFile(square),BlackKing) != 0)
  1022.         return(And(And(AttacksFile(square),RooksQueens),
  1023.                    WhitePieces) != 0);
  1024.       else return(0);
  1025.     case 9:
  1026.       if (And(AttacksDiagh1(square),BlackKing) != 0)
  1027.         return(And(And(AttacksDiagh1(square),BishopsQueens),
  1028.                    WhitePieces) != 0);
  1029.       else return(0);
  1030.     }
  1031.   }
  1032.   return(0);
  1033. }
  1034.  
  1035. void Print(int vb, char *fmt, ...)
  1036. {
  1037.   va_list ap;
  1038.   va_start(ap,fmt);
  1039.   if (vb&display_options) vprintf(fmt, ap);
  1040.   fflush(stdout);
  1041.   if (time_limit>99 || tc_time_remaining>6000 || vb==4095) {
  1042.     if (log_file) vfprintf(log_file, fmt, ap);
  1043.     if (log_file) fflush(log_file);
  1044.   }
  1045.   va_end(ap);
  1046. }
  1047.  
  1048. /*
  1049.  
  1050. A 32 bit random number generator. An implementation in C of the algorithm given by
  1051. Knuth, the art of computer programming, vol. 2, pp. 26-27. We use e=32, so
  1052. we have to evaluate y(n) = y(n - 24) + y(n - 55) mod 2^32, which is implicitly
  1053. done by unsigned arithmetic.
  1054.  
  1055. */
  1056.  
  1057. unsigned int Random32(void)
  1058. {
  1059.   /*
  1060.   random numbers from Mathematica 2.0.
  1061.   SeedRandom = 1;
  1062.   Table[Random[Integer, {0, 2^32 - 1}]
  1063.   */
  1064.   static unsigned long x[55] = {
  1065.     1410651636UL, 3012776752UL, 3497475623UL, 2892145026UL, 1571949714UL,
  1066.     3253082284UL, 3489895018UL, 387949491UL, 2597396737UL, 1981903553UL,
  1067.     3160251843UL, 129444464UL, 1851443344UL, 4156445905UL, 224604922UL,
  1068.     1455067070UL, 3953493484UL, 1460937157UL, 2528362617UL, 317430674UL,
  1069.     3229354360UL, 117491133UL, 832845075UL, 1961600170UL, 1321557429UL,
  1070.     747750121UL, 545747446UL, 810476036UL, 503334515UL, 4088144633UL,
  1071.     2824216555UL, 3738252341UL, 3493754131UL, 3672533954UL, 29494241UL,
  1072.     1180928407UL, 4213624418UL, 33062851UL, 3221315737UL, 1145213552UL,
  1073.     2957984897UL, 4078668503UL, 2262661702UL, 65478801UL, 2527208841UL,
  1074.     1960622036UL, 315685891UL, 1196037864UL, 804614524UL, 1421733266UL,
  1075.     2017105031UL, 3882325900UL, 810735053UL, 384606609UL, 2393861397UL };
  1076.   static int init = 1;
  1077.   static unsigned long y[55];
  1078.   static int j, k;
  1079.   unsigned long ul;
  1080.  
  1081.   if (init)
  1082.   {
  1083.     int i;
  1084.  
  1085.     init = 0;
  1086.     for (i = 0; i < 55; i++) y[i] = x[i];
  1087.     j = 24 - 1;
  1088.     k = 55 - 1;
  1089.   }
  1090.  
  1091.   ul = (y[k] += y[j]);
  1092.   if (--j < 0) j = 55 - 1;
  1093.   if (--k < 0) k = 55 - 1;
  1094.   return((unsigned int)ul);
  1095. }
  1096.  
  1097. BITBOARD Random64(void)
  1098. {
  1099.   BITBOARD result;
  1100.   unsigned int r1, r2;
  1101.  
  1102.   r1=Random32();
  1103.   r2=Random32();
  1104.   result=Or(r1,Shiftl((BITBOARD) r2,32));
  1105.   return (result);
  1106. }
  1107.  
  1108. /* last modified 05/06/97 */
  1109. /*
  1110. ********************************************************************************
  1111. *                                                                              *
  1112. *   Read() copies data from the command_buffer into a local buffer, and then   *
  1113. *   uses ReadParse to break this command up into tokens for processing.        *
  1114. *                                                                              *
  1115. ********************************************************************************
  1116. */
  1117. int Read(int wait, char *buffer) {
  1118.   char *eol, *ret, readdata;
  1119.  
  1120.   *buffer=0;
  1121. /*
  1122.    case 1:  we have a complete command line, with terminating
  1123.    N/L character in the buffer.  we can simply extract it from
  1124.    the I/O buffer, parse it and return.
  1125. */
  1126.   if (strchr(cmd_buffer,'\n'));
  1127. /*
  1128.    case 2:  the buffer does not contain a complete line.  If we
  1129.    were asked to not wait for a complete command, then we first
  1130.    see if I/O is possible, and if so, read in what is available.
  1131.    If that includes a N/L, then we are ready to parse and return.
  1132.    If not, we return indicating no input available just yet.
  1133. */
  1134.   else if (!wait) {
  1135.     if (CheckInput()) {
  1136.       readdata=ReadInput();
  1137.       if (!strchr(cmd_buffer,'\n')) return(0);
  1138.       if (!readdata) return(-1);
  1139.     }
  1140.     else return(0);
  1141.   }
  1142. /*
  1143.    case 3:  the buffer does not contain a complete line, but we
  1144.    were asked to wait until a complete command is entered.  So we
  1145.    hang by doing a ReadInput() and continue doing so until we get
  1146.    a N/L character in the buffer.  Then we parse and return.
  1147. */
  1148.   else while (!strchr(cmd_buffer,'\n')) {
  1149.     readdata=ReadInput();
  1150.     if (!readdata) return(-1);
  1151.   }
  1152.  
  1153.   eol=strchr(cmd_buffer,'\n');
  1154.   *eol=0;
  1155.   ret=strchr(cmd_buffer,'\r');
  1156.   if (ret) *ret=' ';
  1157.   strcpy(buffer,cmd_buffer);
  1158.   memmove(cmd_buffer,eol+1,strlen(eol+1)+1);
  1159.   return(1);
  1160. }
  1161.  
  1162. /* last modified 04/23/97 */
  1163. /*
  1164. ********************************************************************************
  1165. *                                                                              *
  1166. *   ReadClear() clears the input buffer when input_stream is being switched to *
  1167. *   a file, since we have info buffered up from a different input stream.      *
  1168. *                                                                              *
  1169. ********************************************************************************
  1170. */
  1171. void ReadClear() {
  1172.   cmd_buffer[0]=0;
  1173. }
  1174.  
  1175. /* last modified 05/06/97 */
  1176. /*
  1177. ********************************************************************************
  1178. *                                                                              *
  1179. *   ReadParse() takes one complete command-line, and breaks it up into tokens. *
  1180. *   common delimiters are used, such as " ", ",", "/" and ";", any of which    *
  1181. *   delimit fields.                                                            *
  1182. *                                                                              *
  1183. ********************************************************************************
  1184. */
  1185. int ReadParse(char *buffer, char *args[], char *delims) {
  1186.   char *next, tbuffer[512];
  1187.   int nargs;
  1188.  
  1189.   strcpy(tbuffer,buffer);
  1190.   for (nargs=0;nargs<16;nargs++) *(args[nargs])=0;
  1191.   next=strtok(tbuffer,delims);
  1192.   if (!next) return(0);
  1193.   strcpy(args[0],next);
  1194.   for (nargs=1;nargs<32;nargs++) {
  1195.     next=strtok(0,delims);
  1196.     if (!next) break;
  1197.     strcpy(args[nargs],next);
  1198.   }
  1199.   return(nargs);
  1200. }
  1201.  
  1202. /* last modified 04/23/97 */
  1203. /*
  1204. ********************************************************************************
  1205. *                                                                              *
  1206. *   ReadInput() reads data from the input_stream, and buffers this into the    *
  1207. *   command_buffer for later processing.                                       *
  1208. *                                                                              *
  1209. ********************************************************************************
  1210. */
  1211. int ReadInput(void) {
  1212.   char buffer[512], *end;
  1213.   int bytes;
  1214.  
  1215. #if defined(MACOS)
  1216.   gets((char *) &buffer);
  1217.   bytes=strlen(buffer);
  1218.   end=cmd_buffer+strlen(cmd_buffer);
  1219.   memcpy(end,buffer,bytes);
  1220.   *(end+bytes)='\n';
  1221.   *(end+bytes+1)=0;
  1222. #else
  1223.   do
  1224.     bytes=read(fileno(input_stream),buffer,512);
  1225.   while (bytes<0 && errno==EINTR);
  1226.   if (bytes == 0) {
  1227.     if (input_stream != stdin) fclose(input_stream);
  1228.     input_stream=stdin;
  1229.     return(0);
  1230.   }
  1231.   else if (bytes < 0) {
  1232.     Print(4095,"ERROR!  input I/O stream is unreadable, exiting.\n");
  1233.     exit(1);
  1234.   }
  1235.   end=cmd_buffer+strlen(cmd_buffer);
  1236.   memcpy(end,buffer,bytes);
  1237.   *(end+bytes)=0;
  1238. #endif
  1239.   return(1);
  1240. }
  1241.  
  1242. /* last modified 10/11/96 */
  1243. /*
  1244. ********************************************************************************
  1245. *                                                                              *
  1246. *   ReadChessMove() is used to read a move from an input file.  the main issue *
  1247. *   is to skip over "trash" like move numbers, times, comments, and so forth,  *
  1248. *   and find the next actual move.                                             *
  1249. *                                                                              *
  1250. ********************************************************************************
  1251. */
  1252. int ReadChessMove(TREE *tree, FILE *input, int wtm, int one_move) {
  1253.  
  1254.   static char text[128];
  1255.   char *tmove;
  1256.   int move=0, status;
  1257.  
  1258.   while (move == 0) {
  1259.     status=fscanf(input,"%s",text);
  1260.     if (status <= 0) return(-1);
  1261.     if (strcmp(text,"0-0") && strcmp(text,"0-0-0"))
  1262.       tmove=text+strspn(text,"0123456789.");
  1263.     else
  1264.       tmove=text;
  1265.     if (((tmove[0]>='a' && tmove[0]<='z') ||
  1266.          (tmove[0]>='A' && tmove[0]<='Z')) ||
  1267.         !strcmp(tmove,"0-0") || !strcmp(tmove,"0-0-0")) {
  1268.       if (!strcmp(tmove,"exit")) return(-1);
  1269.       move=InputMove(tree,tmove,0,wtm,1,0);
  1270.     }
  1271.     if (one_move) break;
  1272.   }
  1273.   return(move);
  1274. }
  1275.  
  1276. /* last modified 05/13/97 */
  1277. /*
  1278. ********************************************************************************
  1279. *                                                                              *
  1280. *   ReadNextMove() is used to take a text chess move from a file, and see if   *
  1281. *   if is legal, skipping a sometimes embedded move number (1.e4 for example)  *
  1282. *   to make PGN import easier.                                                 *
  1283. *                                                                              *
  1284. ********************************************************************************
  1285. */
  1286. int ReadNextMove(TREE *tree, char *text, int ply, int wtm) {
  1287.  
  1288.   char *tmove;
  1289.   int move=0;
  1290.  
  1291.   if (strcmp(text,"0-0") && strcmp(text,"0-0-0"))
  1292.     tmove=text+strspn(text,"0123456789./-");
  1293.   else
  1294.     tmove=text;
  1295.   if (((tmove[0]>='a' && tmove[0]<='z') ||
  1296.        (tmove[0]>='A' && tmove[0]<='Z')) ||
  1297.       !strcmp(tmove,"0-0") || !strcmp(tmove,"0-0-0")) {
  1298.     if (!strcmp(tmove,"exit")) return(-1);
  1299.     move=InputMove(tree,tmove,ply,wtm,1,0);
  1300.   }
  1301.   return(move);
  1302. }
  1303.  
  1304. /* last modified 06/15/98 */
  1305. /*
  1306. ********************************************************************************
  1307. *                                                                              *
  1308. *   this routine reads a move from a PGN file to build an opening book or for  *
  1309. *   annotating.  It returns a 1 if a header is read, it returns a 0 if a move  *
  1310. *   is read, and returns a -1 on end of file.  It counts lines and this        *
  1311. *   counter can be accessed by calling this function with a non-zero second    *
  1312. *   formal parameter.                                                          *
  1313. *                                                                              *
  1314. ********************************************************************************
  1315. */
  1316. int ReadPGN(FILE *input, int option) {
  1317.   static int data=0, lines_read=0;
  1318.   static char input_buffer[512];
  1319.   char temp[512], *eof, analysis_move[64];
  1320.   int braces=0, parens=0, brackets=0, analysis=0, last_good_line;
  1321.  
  1322. /*
  1323.  ----------------------------------------------------------
  1324. |                                                          |
  1325. |  if the line counter is being requested, return it with  |
  1326. |  no other changes being made.  if "purge" is true, clear |
  1327. |  the current input buffer.                               |
  1328. |                                                          |
  1329.  ----------------------------------------------------------
  1330. */
  1331.   pgn_suggested_percent=0;
  1332.   if (!input) {
  1333.     lines_read=0;
  1334.     data=0;
  1335.     return(0);
  1336.   }
  1337.   if (option==-1) data=0;
  1338.   if (option==-2) return(lines_read);
  1339. /*
  1340.  ----------------------------------------------------------
  1341. |                                                          |
  1342. |  if we don't have any data in the buffer, the first step |
  1343. |  is to read the next line.                               |
  1344. |                                                          |
  1345.  ----------------------------------------------------------
  1346. */
  1347.   while (1) {
  1348.     if (!data) {
  1349.       eof=fgets(input_buffer,512,input);
  1350.       if (!eof) return(-1);
  1351.       if (strchr(input_buffer,'\n')) *strchr(input_buffer,'\n')=0;
  1352.       if (strchr(input_buffer,'\r')) *strchr(input_buffer,'\r')=' ';
  1353.       lines_read++;
  1354.       buffer[0]=0;
  1355.       sscanf(input_buffer,"%s",buffer);
  1356.       if (buffer[0] == '[') do {
  1357.         char *bracket1, *bracket2, value[128];
  1358.         strcpy(buffer,input_buffer);
  1359.         bracket1=strchr(input_buffer,'\"');
  1360.         if (bracket1 == 0) return(1);
  1361.         bracket2=strchr(bracket1+1,'\"');
  1362.         if (bracket2 == 0) return(1);
  1363.         *bracket2=0;
  1364.         strcpy(value,bracket1+1);
  1365.         if (strstr(input_buffer,"Event")) strcpy(pgn_event,value);
  1366.         else if (strstr(input_buffer,"Site")) strcpy(pgn_site,value);
  1367.         else if (strstr(input_buffer,"Round")) strcpy(pgn_round,value);
  1368.         else if (strstr(input_buffer,"Date")) strcpy(pgn_date,value);
  1369.         else if (strstr(input_buffer,"WhiteElo")) strcpy(pgn_white_elo,value);
  1370.         else if (strstr(input_buffer,"White")) strcpy(pgn_white,value);
  1371.         else if (strstr(input_buffer,"BlackElo")) strcpy(pgn_black_elo,value);
  1372.         else if (strstr(input_buffer,"Black")) strcpy(pgn_black,value);
  1373.         else if (strstr(input_buffer,"Result")) strcpy(pgn_result,value);
  1374.         else if (strstr(input_buffer,"FEN")) {
  1375.           sprintf(buffer,"setboard %s",value);
  1376.           (void) Option(local[0]);
  1377.           continue;
  1378.         }
  1379.         return(1);
  1380.       } while(0);
  1381.       data=1;
  1382.     }
  1383. /*
  1384.  ----------------------------------------------------------
  1385. |                                                          |
  1386. |  if we already have data in the buffer, it is just a     |
  1387. |  matter of extracting the next move and returning it to  |
  1388. |  the caller.  if the buffer is empty, another line has   |
  1389. |  to be read in.                                          |
  1390. |                                                          |
  1391.  ----------------------------------------------------------
  1392. */
  1393.     else {
  1394.       buffer[0]=0;
  1395.       sscanf(input_buffer,"%s",buffer);
  1396.       if (strlen(buffer) == 0) {
  1397.         data=0;
  1398.         continue;
  1399.       }
  1400.       else {
  1401.         char *skip;
  1402.         strcpy(temp,input_buffer);
  1403.         skip=strstr(input_buffer,buffer)+strlen(buffer);
  1404.         if (skip) strcpy(input_buffer,skip);
  1405.       }
  1406. /*
  1407.  ----------------------------------------------------------
  1408. |                                                          |
  1409. |  this skips over nested { or ( characters and finds the  |
  1410. |  'mate', before returning any more moves.  it also stops |
  1411. |  if a PGN header is encountered, probably due to an      |
  1412. |  incorrectly bracketed analysis variation.               |
  1413. |                                                          |
  1414.  ----------------------------------------------------------
  1415. */
  1416.       last_good_line=lines_read;
  1417.       analysis_move[0]=0;
  1418.       if (strchr(buffer,'{') || strchr(buffer,'(')) while (1) {
  1419.         char *skip, *ch;
  1420.         analysis=1;
  1421.         while ((ch=strpbrk(buffer,"(){}[]"))) {
  1422.           if (*ch == '(') {
  1423.             *strchr(buffer,'(')=' ';
  1424.             if (!braces) parens++;
  1425.           }
  1426.           if (*ch == ')') {
  1427.             *strchr(buffer,')')=' ';
  1428.             if (!braces) parens--;
  1429.           }
  1430.           if (*ch == '{') {
  1431.             *strchr(buffer,'{')=' ';
  1432.             braces++;
  1433.           }
  1434.           if (*ch == '}') {
  1435.             *strchr(buffer,'}')=' ';
  1436.             braces--;
  1437.           }
  1438.           if (*ch == '[') {
  1439.             *strchr(buffer,'[')=' ';
  1440.             if (!braces) brackets++;
  1441.           }
  1442.           if (*ch == ']') {
  1443.             *strchr(buffer,']')=' ';
  1444.             if (!braces) brackets--;
  1445.           }
  1446.         }
  1447.         if (analysis && analysis_move[0]==0) {
  1448.           if (strspn(buffer," ") != strlen(buffer)) {
  1449.             char *tmove=analysis_move;
  1450.             sscanf(buffer,"%64s",analysis_move);
  1451.             strcpy(buffer,analysis_move);
  1452.             if (strcmp(buffer,"0-0") && strcmp(buffer,"0-0-0"))
  1453.               tmove=buffer+strspn(buffer,"0123456789.");
  1454.             else
  1455.               tmove=buffer;
  1456.             if ((tmove[0]>='a' && tmove[0]<='z') ||
  1457.                 (tmove[0]>='A' && tmove[0]<='Z') ||
  1458.                 !strcmp(tmove,"0-0") || !strcmp(tmove,"0-0-0"))
  1459.               strcpy(analysis_move,buffer);
  1460.             else
  1461.               analysis_move[0]=0;
  1462.           }
  1463.         }
  1464.         if (parens==0 && braces==0 && brackets==0) break;
  1465.         buffer[0]=0;
  1466.         sscanf(input_buffer,"%s",buffer);
  1467.         if (strlen(buffer) == 0) {
  1468.           eof=fgets(input_buffer,512,input);
  1469.           if (!eof) {
  1470.             parens=0;
  1471.             braces=0;
  1472.             brackets=0;
  1473.             return(-1);
  1474.           }
  1475.           if (strchr(input_buffer,'\n')) *strchr(input_buffer,'\n')=0;
  1476.           if (strchr(input_buffer,'\r')) *strchr(input_buffer,'\r')=' ';
  1477.           lines_read++;
  1478.           if (lines_read-last_good_line >= 100) {
  1479.             parens=0;
  1480.             braces=0;
  1481.             brackets=0;
  1482.             Print(4095,"ERROR.  comment spans over 100 lines, starting at line %d\n",
  1483.                   last_good_line);
  1484.             break;
  1485.           }
  1486.         }
  1487.         strcpy(temp,input_buffer);
  1488.         skip=strstr(input_buffer,buffer)+strlen(buffer);
  1489.         strcpy(input_buffer,skip);
  1490.       }
  1491.       else {
  1492.         int skip;
  1493.         if ((skip=strspn(buffer,"0123456789."))) {
  1494.           char temp[512];
  1495.           strcpy(temp,buffer+skip);
  1496.           strcpy(buffer,temp);
  1497.         }
  1498.         if (isalpha(buffer[0]) || strchr(buffer,'-')) {
  1499.           char *first, *last, *percent;
  1500.           first=input_buffer+strspn(input_buffer," ");
  1501.           if (first==0 || *first != '{') return(0);
  1502.           last=strchr(input_buffer,'}');
  1503.           if (last == 0) return(0);
  1504.           percent=strstr(first,"play");
  1505.           if (percent == 0) return(0);
  1506.           pgn_suggested_percent=atoi(percent+4+strspn(percent+4," "));
  1507.           return(0);
  1508.         }
  1509.       }
  1510.       if (analysis_move[0] && option==1) {
  1511.         strcpy(buffer,analysis_move);
  1512.         return(2);
  1513.       }
  1514.     }
  1515.   }
  1516.   return(-1);
  1517. }
  1518.  
  1519. /* last modified 06/10/98 */
  1520. /*
  1521. ********************************************************************************
  1522. *                                                                              *
  1523. *   RestoreGame() resets the position to the beginning of the game, and then   *
  1524. *   reads in the game.nnn history file to set the position up so that the game *
  1525. *   position matches the position at the end of the history file.              *
  1526. *                                                                              *
  1527. ********************************************************************************
  1528. */
  1529. void RestoreGame(void) {
  1530.   int i, move;
  1531.   char cmd[16];
  1532.   wtm=1;
  1533.   InitializeChessBoard(&local[0]->position[0]);
  1534.   for (i=0;i<500;i++) {
  1535.     fseek(history_file,i*10,SEEK_SET);
  1536.     strcpy(cmd,"");
  1537.     fscanf(history_file,"%s",cmd);
  1538.     if (strcmp(cmd,"pass")) {
  1539.       move=InputMove(local[0],cmd,0,wtm,1,0);
  1540.       if (move) MakeMoveRoot(local[0],move,wtm);
  1541.       else break;
  1542.     }
  1543.     wtm=ChangeSide(wtm);
  1544.   }
  1545.   Phase();
  1546. }
  1547.  
  1548. char* Reverse(void) {
  1549. #if defined(NT_i386) || defined(NT_AXP)
  1550.   HANDLE  std_console;
  1551.   std_console = GetStdHandle(STD_OUTPUT_HANDLE);
  1552. #endif
  1553.  
  1554.   if (ansi) {
  1555. #if defined(UNIX) || defined(AMIGA)
  1556.     return("\033[7m");
  1557. #elif defined(NT_i386) || defined(NT_AXP)
  1558.     SetConsoleTextAttribute(std_console, BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
  1559.     return("");
  1560. #else
  1561.     return("\033[7;47;33m");
  1562. #endif
  1563.   }
  1564.   return("");
  1565. }
  1566.  
  1567. #if defined(COMPACT_ATTACKS)
  1568.  
  1569. #if !defined(USE_ASSEMBLY_A)
  1570.  
  1571. BITBOARD AttacksDiaga1Func (DIAG_INFO *diag, POSITION *boardp)
  1572. {
  1573.   return AttacksDiaga1Int(diag,boardp);
  1574. }
  1575.  
  1576. BITBOARD AttacksDiagh1Func(DIAG_INFO *diag, POSITION *boardp)
  1577. {
  1578.   return AttacksDiagh1Int(diag,boardp);
  1579. }
  1580.  
  1581. BITBOARD AttacksFileFunc(int square, POSITION *boardp)
  1582. {
  1583.   return AttacksFileInt(square,boardp);
  1584. }
  1585.  
  1586. BITBOARD AttacksRankFunc(int square, POSITION *boardp)
  1587. {
  1588.   BITBOARD tmp = Or((boardp)->w_occupied, (boardp)->b_occupied);
  1589.  
  1590.   unsigned char tmp2 =
  1591.     at.rank_attack_bitboards[File(square)]
  1592.       [at.which_attack[File(square)]
  1593.         [And(SplitShiftr(tmp,(Rank(~(square))<<3)+1),0x3f) ] ];
  1594.  
  1595.   return SplitShiftl (tmp2, Rank(~(square))<<3);
  1596. }
  1597.  
  1598. BITBOARD AttacksBishopFunc(DIAG_INFO *diag, POSITION *boardp)
  1599. {
  1600.   return Or(AttacksDiaga1Int(diag,boardp),
  1601.       AttacksDiagh1Int(diag,boardp));
  1602. }
  1603.  
  1604. BITBOARD AttacksRookFunc(int square, POSITION *boardp)
  1605. {
  1606.   BITBOARD tmp = Or((boardp)->w_occupied, (boardp)->b_occupied);
  1607.  
  1608.   unsigned char tmp2 =
  1609.     at.rank_attack_bitboards[File(square)][at.which_attack[File(square)]
  1610.         [And(SplitShiftr(tmp,(Rank(~(square))<<3)+1),0x3f)]];
  1611.  
  1612.   return Or(SplitShiftl (tmp2, Rank(~(square))<<3),
  1613.       AttacksFileInt(square,boardp));
  1614. }
  1615.  
  1616. unsigned MobilityDiaga1Func(DIAG_INFO *diag, POSITION *boardp)
  1617. {
  1618.   return MobilityDiaga1Int(diag,boardp);
  1619. }
  1620.  
  1621. unsigned MobilityDiagh1Func(DIAG_INFO *diag, POSITION *boardp)
  1622. {
  1623.   return MobilityDiagh1Int(diag,boardp);
  1624. }
  1625.  
  1626. unsigned MobilityFileFunc(int square, POSITION *boardp)
  1627. {
  1628.   return MobilityFileInt (square,boardp);
  1629. }
  1630.  
  1631. unsigned MobilityRankFunc(int square, POSITION *boardp)
  1632. {
  1633.   return MobilityRankInt (square,boardp);
  1634. }
  1635.  
  1636. #endif
  1637.  
  1638. unsigned char bishop_shift_rl45[64] = {
  1639.           59, 57, 54, 50, 45, 39, 32,  0,
  1640.           57, 54, 50, 45, 39, 32,  0,  8,
  1641.           54, 50, 45, 39, 32,  0,  8, 15,
  1642.           50, 45, 39, 32,  0,  8, 15, 21,
  1643.           45, 39, 32,  0,  8, 15, 21, 60,
  1644.           39, 32,  0,  8, 15, 21, 60, 26,
  1645.           32,  0,  8, 15, 21, 60, 26, 29,
  1646.            0,  8, 15, 21, 60, 26, 29, 31 };
  1647.  
  1648. unsigned char bishop_shift_rr45[64] = {
  1649.             0,  8, 15, 21, 60, 26, 29, 31,
  1650.            32,  0,  8, 15, 21, 60, 26, 29,
  1651.            39, 32,  0,  8, 15, 21, 60, 26,
  1652.            45, 39, 32,  0,  8, 15, 21, 60,
  1653.            50, 45, 39, 32,  0,  8, 15, 21,
  1654.            54, 50, 45, 39, 32,  0,  8, 15,
  1655.            57, 54, 50, 45, 39, 32,  0,  8,
  1656.            59, 57, 54, 50, 45, 39, 32,  0 };
  1657.  
  1658.  
  1659. unsigned char init_l45[64] = {
  1660.               4,  5,  7, 10, 14, 19, 25, 56,
  1661.               6,  8, 11, 15, 20, 26, 57, 49,
  1662.               9, 12, 16, 21, 27, 58, 50, 43,
  1663.              13, 17, 22, 28, 59, 51, 44, 38,
  1664.              18, 23, 29, 60, 52, 45, 39,  0,
  1665.              24, 30, 61, 53, 46, 40,  1, 35,
  1666.              31, 62, 54, 47, 41,  2, 36, 33,
  1667.              63, 55, 48, 42,  3, 37, 34, 32 };
  1668.  
  1669. unsigned char init_r45[64] = {
  1670.              56, 49, 43, 38,  0, 35, 33, 32,
  1671.              25, 57, 50, 44, 39,  1, 36, 34,
  1672.              19, 26, 58, 51, 45, 40,  2, 37,
  1673.              14, 20, 27, 59, 52, 46, 41,  3,
  1674.              10, 15, 21, 28, 60, 53, 47, 42,
  1675.               7, 11, 16, 22, 29, 61, 54, 48,
  1676.               5,  8, 12, 17, 23, 30, 62, 55,
  1677.               4,  6,  9, 13, 18, 24, 31, 63 };
  1678.  
  1679. unsigned char init_l90[64] = {
  1680.         0,  8, 16, 24, 32, 40, 48, 56,
  1681.         1,  9, 17, 25, 33, 41, 49, 57,
  1682.         2, 10, 18, 26, 34, 42, 50, 58,
  1683.         3, 11, 19, 27, 35, 43, 51, 59,
  1684.         4, 12, 20, 28, 36, 44, 52, 60,
  1685.         5, 13, 21, 29, 37, 45, 53, 61,
  1686.         6, 14, 22, 30, 38, 46, 54, 62,
  1687.         7, 15, 23, 31, 39, 47, 55, 63 };
  1688.  
  1689. /* How many attacks are there on a length n gfile from square m */
  1690. /*                             N  M */
  1691. static unsigned char n_attacks[9][8] =
  1692. {
  1693.   {  0 },
  1694.   {  1 },
  1695.   {  1,  1 },
  1696.   {  2,  1,  2 },
  1697.   {  3,  2,  2,  3 },
  1698.   {  4,  3,  4,  3,  4 },
  1699.   {  5,  4,  6,  6,  4,  5 },
  1700.   {  6,  5,  8,  9,  8,  5,  6 },
  1701.   {  7,  6, 10, 12, 12, 10,  6,  7}
  1702. };
  1703.  
  1704. /* How many attacks are there from all squares on a gfile of length n. */
  1705. static unsigned char n_length_attacks[9] =
  1706. { 0, 1, 2, 5, 10, 18, 30, 47, 70 };
  1707.  
  1708. #define NDIAG           (7 + 1 + 7)
  1709. #define NGFILES (NDIAG + NDIAG + 1 + 1)
  1710.  
  1711. static struct gfile_info {
  1712.   BITBOARD *bitboard;
  1713.   unsigned char length;
  1714.   unsigned char *map;
  1715.   unsigned char *mobility;
  1716.   unsigned char inc;
  1717. } gfiles[NGFILES];
  1718.  
  1719. /* For each diagonal, a map from index on that diagonal to bit index */
  1720. /* in the normal bitboard representation. */
  1721. static unsigned char diag_map [NDIAG] [8];
  1722.  
  1723. /* For each anti diagonal, a map from index to bitboard map. */
  1724. static unsigned char anti_diag_map [NDIAG] [8];
  1725.  
  1726. /* For the representative file, a map from index to bitboard map. */
  1727. static unsigned char file_map [8];
  1728.  
  1729. /* For the representative rank, a map from index to bitboard map. */
  1730. static unsigned char rank_map [8];
  1731.  
  1732. #define MASK(bits)  (~((~0) << (bits)))
  1733.  
  1734. #define SQ(r,f) (((r)<<3) | (f))
  1735.  
  1736. #define DIAG_LENGTH(sq) (8 - (Rank(sq) > File(sq) ?  \
  1737.             Rank(sq) - File(sq) :  \
  1738.             File(sq) - Rank(sq)))
  1739.  
  1740. #define ANTI_LENGTH(sq) (8 - (Rank(sq) > File(~sq) ?  \
  1741.             Rank(sq) - File(~sq) :  \
  1742.             File(~sq) - Rank(sq)))
  1743.  
  1744. static void InitializeMaps(BITBOARD *temp_rank_attack_bitboards)
  1745. {
  1746.   int file, rank;
  1747.   int diag;
  1748.   int gfile;
  1749.   BITBOARD *b;
  1750.   unsigned char *m;
  1751.   unsigned char *mobility_for_length[9];
  1752.   unsigned char diag_base [NDIAG] =
  1753.     { SQ(7,0), SQ(6,0), SQ(5,0), SQ(4,0), SQ(3,0), SQ(2,0), SQ(1,0), SQ(0,0),
  1754.       SQ(0,1), SQ(0,2), SQ(0,3), SQ(0,4), SQ(0,5), SQ(0,6), SQ(0,7) };
  1755.   unsigned char anti_base[NDIAG] =
  1756.     { SQ(0,0), SQ(0,1), SQ(0,2), SQ(0,3), SQ(0,4), SQ(0,5), SQ(0,6), SQ(0,7),
  1757.       SQ(1,7), SQ(2,7), SQ(3,7), SQ(4,7), SQ(5,7), SQ(6,7), SQ(7,7) };
  1758.  
  1759.   {
  1760.     int i;
  1761.     unsigned char *m = at.short_mobility;
  1762.     for (i = 1; i < 8; i++) {
  1763.       mobility_for_length[i] = m;
  1764.       m += n_length_attacks[i];
  1765.     }
  1766.     mobility_for_length[8] = &at.length8_mobility[0][0];
  1767.   }
  1768.  
  1769.   gfile = 0;
  1770.  
  1771.   b = diag_attack_bitboards;
  1772.   for (diag = 0; diag < NDIAG; diag++, gfile++) {
  1773.     int sq = diag_base[diag];
  1774.     int len = DIAG_LENGTH(sq);
  1775.     int excess = 8 - len;
  1776.     int i;
  1777.  
  1778.     gfiles[gfile].length = len;
  1779.     gfiles[gfile].map = diag_map[diag];
  1780.     gfiles[gfile].bitboard = b;
  1781.     gfiles[gfile].mobility = (diag < 7 ? mobility_for_length[len] : 0);
  1782.     gfiles[gfile].inc = 0;
  1783.     m = mobility_for_length[len];
  1784.     for (i = 0; i < len; i++, sq += 9) {
  1785.       diag_map[diag][i] = sq;
  1786.       diag_info[sq].d_shift = bishop_shift_rr45[sq] + 1 - excess;
  1787.       diag_info[sq].d_mask = MASK(Max(len-2,0)) << excess;
  1788.       diag_info[sq].d_which_attack = &at.which_attack[i][0];
  1789.       diag_info[sq].d_attacks = b;
  1790.       b += n_attacks[len][i];
  1791.       diag_info[sq].d_mobility = m;
  1792.       m += (len == 8 ? MAX_ATTACKS_FROM_SQUARE : n_attacks[len][i]);
  1793.     }
  1794.   }
  1795.  
  1796.   b = anti_diag_attack_bitboards;
  1797.   for (diag = 0; diag < NDIAG; diag++, gfile++) {
  1798.     int sq = anti_base[diag];
  1799.     int len = ANTI_LENGTH(sq);
  1800.     int excess = 8 - len;
  1801.     int i;
  1802.  
  1803.     gfiles[gfile].length = len;
  1804.     gfiles[gfile].map = anti_diag_map[diag];
  1805.     gfiles[gfile].bitboard = b;
  1806.     gfiles[gfile].mobility = 0;
  1807.     gfiles[gfile].inc = 0;
  1808.     m = mobility_for_length[len];
  1809.     for (i = 0; i < len; i++, sq += 7) {
  1810.       anti_diag_map[diag][i] = sq;
  1811.       diag_info[sq].ad_shift = bishop_shift_rl45[sq] + 1 - excess;
  1812.       diag_info[sq].ad_mask = MASK(Max(len-2,0)) << excess;
  1813.       diag_info[sq].ad_which_attack = &at.which_attack[i][0];
  1814.       diag_info[sq].ad_attacks = b;
  1815.       b += n_attacks[len][i];
  1816.       diag_info[sq].ad_mobility = m;
  1817.       m += (len == 8 ? MAX_ATTACKS_FROM_SQUARE : n_attacks[len][i]);
  1818.     }
  1819.   }
  1820.  
  1821.   gfiles[gfile].length = 8;
  1822.   gfiles[gfile].map = file_map;
  1823.   gfiles[gfile].bitboard = &at.file_attack_bitboards[0][0];
  1824.   gfiles[gfile].mobility = &at.length8_mobility[0][0];
  1825.   gfiles[gfile].inc = MAX_ATTACKS_FROM_SQUARE;
  1826.   for (rank = 0; rank < 8; rank++) file_map[rank] = (rank << 3) | 7;
  1827.  
  1828.   gfile++;
  1829.  
  1830.   gfiles[gfile].length = 8;
  1831.   gfiles[gfile].map = rank_map;
  1832.   gfiles[gfile].bitboard = temp_rank_attack_bitboards;
  1833.   gfiles[gfile].mobility = 0;
  1834.   gfiles[gfile].inc = MAX_ATTACKS_FROM_SQUARE;
  1835.   for (file = 0; file < 8; file++) rank_map[file] = file | (7 << 3);
  1836. }
  1837.  
  1838. static void InitializeBrev (unsigned char brev[])
  1839. {
  1840.   unsigned value;
  1841.  
  1842.   for (value = 0; value < 64; value++) {
  1843.     unsigned br = 0;
  1844.     int i;
  1845.     for (i = 0; i < 6; i++) br |= (((value >> i) & 1) << (5 - i));
  1846.       brev[value] = br;
  1847.   }
  1848. }
  1849.  
  1850. #define MakeAttack(lower,upper) ((lower) | ((upper) << 3))
  1851.  
  1852. void ComputeAttacksAndMobility ()
  1853. {
  1854.   BITBOARD temp_rank_attack_bitboards[8][MAX_ATTACKS_FROM_SQUARE];
  1855.   int attacks_seen[MAX_ATTACKS_FROM_SQUARE];
  1856.   int attacker;
  1857.   unsigned g;
  1858.   unsigned char brev[64];
  1859.  
  1860.   InitializeMaps(&temp_rank_attack_bitboards[0][0]);
  1861.   InitializeBrev(brev);
  1862.  
  1863.   for (attacker = 0; attacker < 8; attacker++) {
  1864.     unsigned attacks_found = 0;
  1865.     unsigned gf;
  1866.     memset ((char *)attacks_seen, 0, sizeof attacks_seen);
  1867.     for (g = 0; g < 64; g++) {
  1868.       int a, p, found;
  1869.       unsigned lower, upper, attack;
  1870.       unsigned gfile_value = g << 1;
  1871.  
  1872.       lower = 0;
  1873.       for (p = attacker-1; p >= 0; p--) {
  1874.         lower++;
  1875.         if (gfile_value & (1 << p)) break;
  1876.       }
  1877.       upper = 0;
  1878.       for (p = attacker+1; p < 8; p++) {
  1879.         upper++;
  1880.         if (gfile_value & (1 << p)) break;
  1881.       }
  1882.  
  1883.       attack = MakeAttack(lower,upper);
  1884.       found = 0;
  1885.       for (a=0; a<(int)attacks_found; a++)
  1886.         if ((int)attack == attacks_seen[a]) {
  1887.           found = 1;
  1888.           break;
  1889.         }
  1890.       if (!found) {
  1891.         int gf;
  1892.         attacks_seen[attacks_found] = attack;
  1893.         for (gf = 0; gf < NGFILES; gf++) {
  1894.           unsigned max_attacks = n_attacks[gfiles[gf].length][attacker];
  1895.           if (attacks_found < max_attacks) {
  1896.             BITBOARD b = 0;
  1897.             int i, p;
  1898.             for (p = attacker-1, i = 0; i < (int) lower; i++, p--)
  1899.               Set(gfiles[gf].map[p], b);
  1900.             for (p=attacker+1,i=0;(i<(int) upper) && (p<(int) gfiles[gf].length);
  1901.                  i++, p++)
  1902.               Set(gfiles[gf].map[p], b);
  1903.             if (gfiles[gf].mobility)
  1904.             gfiles[gf].mobility[attacks_found] =
  1905.               lower + Min((int) upper, (int) gfiles[gf].length - attacker - 1);
  1906.             gfiles[gf].bitboard[attacks_found] = b;
  1907.           }
  1908.         }
  1909.         attacks_found++;
  1910.       }
  1911.       at.which_attack[attacker][brev[g]] = a;
  1912.     }
  1913.     for (gf = 0; gf < NGFILES; gf++) {
  1914.       unsigned len = gfiles[gf].length;
  1915.       unsigned this_inc =
  1916.         (gfiles[gf].inc ? gfiles[gf].inc : n_attacks[len][attacker]);
  1917.       if ((unsigned) attacker < len) {
  1918.         if (gfiles[gf].mobility) gfiles[gf].mobility += this_inc;
  1919.         gfiles[gf].bitboard += this_inc;
  1920.       }
  1921.     }
  1922.   }
  1923.   {
  1924.     int i, a;
  1925.     for (i = 0; i < 8; i++)
  1926.       for (a = 0; a < MAX_ATTACKS_FROM_SQUARE; a++)
  1927.         at.rank_attack_bitboards[i][a]=
  1928.           temp_rank_attack_bitboards[i][a] & 0xff;
  1929.   }
  1930. }
  1931. #endif
  1932.  
  1933. /*
  1934. ********************************************************************************
  1935. *                                                                              *
  1936. *   Whisper() is used to whisper/kibitz information to a chess server.  it has *
  1937. *   to handle the xboard whisper/kibitz interface as well as the custom ics    *
  1938. *   interface for Crafty.  there are two main issues:  (a) presenting only the *
  1939. *   information specified by the current value of whisper or kibitz variables; *
  1940. *   (a) if using the custom ICS interface, preceeding the commands with a "*"  *
  1941. *   so the interface will direct them to the server rather than the operator.  *
  1942. *                                                                              *
  1943. ********************************************************************************
  1944. */
  1945. void Whisper(int level,int depth,int time,int value,unsigned int nodes,
  1946.              int cpu,char* pv)
  1947. {
  1948.   if (!puzzling) {
  1949.     char prefix[128];
  1950.  
  1951.     if (strlen(channel_title) && channel)
  1952.       sprintf(prefix,"tell %d (%s) ",channel, channel_title);
  1953.     else if (channel) sprintf(prefix,"tell %d",channel);
  1954.     else sprintf(prefix,"whisper");
  1955.     switch (level) {
  1956.     case 1:
  1957.       if (kibitz && (value > 0)) {
  1958.         if (ics) printf("*");
  1959.         printf("kibitz mate in %d moves.\n\n",value);
  1960.       }
  1961.       else if (whisper && (value > 0)) {
  1962.         if (ics) printf("*");
  1963.         printf("%s mate in %d moves.\n\n",prefix,value);
  1964.       }
  1965.       if (kibitz && (value < 0)) {
  1966.         if (ics) printf("*");
  1967.         printf("%s mated in %d moves.\n\n",prefix,-value);
  1968.       }
  1969.       break;
  1970.     case 2:
  1971.       if (kibitz >= 2) {
  1972.         if (ics) printf("*");
  1973.         printf("kibitz d%d; %s; nps %d; time %s; cpu %d%%; p:%d\n",
  1974.                depth,DisplayEvaluationWhisper(value),
  1975.                (time)?100*nodes/time:nodes,DisplayTimeWhisper(time),cpu,predicted);
  1976.       }
  1977.       else if (whisper >= 2) {
  1978.         if (ics) printf("*");
  1979.         printf("%s d%d; %s; nps %d; time %s; cpu %d%%; p:%d\n",
  1980.                prefix,depth,DisplayEvaluationWhisper(value),
  1981.                (time)?100*nodes/time:nodes,DisplayTimeWhisper(time),cpu,predicted);
  1982.       }
  1983.     case 3:
  1984.       if ((kibitz >= 3) && (nodes>5000 || level==2)) {
  1985.         if (ics) printf("*");
  1986.         printf("kibitz pv:%s\n",pv);
  1987.       }
  1988.       else if ((whisper >= 3) && (nodes>5000 || level==2)) {
  1989.         if (ics) printf("*");
  1990.         printf("%s pv:%s\n",prefix,pv);
  1991.       }
  1992.       break;
  1993.     case 4:
  1994.       if (kibitz >= 4) {
  1995.         if (ics) printf("*");
  1996.         printf("kibitz %s\n",pv);
  1997.       }
  1998.       else if (whisper >= 4) {
  1999.         if (ics) printf("*");
  2000.         printf("%s %s\n",prefix,pv);
  2001.       }
  2002.       break;
  2003.     case 5:
  2004.       if (kibitz>=5 && nodes>5000) {
  2005.         if (ics) printf("*");
  2006.         printf("kibitz d%d-> %s %s %s\n",depth, DisplayTimeWhisper(time),
  2007.                                        DisplayEvaluationWhisper(value),pv);
  2008.       }
  2009.       else if (whisper>=5 && nodes>5000) {
  2010.         if (ics) printf("*");
  2011.         printf("%s d%d-> %s %s %s\n",prefix,depth, DisplayTimeWhisper(time),
  2012.                                        DisplayEvaluationWhisper(value),pv);
  2013.       }
  2014.       break;
  2015.     case 6:
  2016.       if (kibitz>=6 && nodes>5000) {
  2017.         if (ics) printf("*");
  2018.         if (cpu == 0)
  2019.           printf("kibitz d%d+ %s %s %s\n",depth, DisplayTimeWhisper(time),
  2020.                                            DisplayEvaluationWhisper(value),pv);
  2021.         else
  2022.           printf("kibitz d%d+ %s >(%s) %s <re-searching>\n",depth,
  2023.                  DisplayTimeWhisper(time),DisplayEvaluationWhisper(value),pv);
  2024.       }
  2025.       else if (whisper>=6 && nodes>5000) {
  2026.         if (ics) printf("*");
  2027.         if (cpu == 0)
  2028.           printf("%s d%d+ %s %s %s\n",prefix,depth, DisplayTimeWhisper(time),
  2029.                                             DisplayEvaluationWhisper(value),pv);
  2030.         else
  2031.           printf("%s d%d+ %s >(%s) %s <re-searching>\n",prefix,depth,
  2032.                  DisplayTimeWhisper(time),DisplayEvaluationWhisper(value),pv);
  2033.       }
  2034.       break;
  2035.     }
  2036.     if (post && level>1) {
  2037.       if (strstr(pv,"book"))
  2038.         printf("    %2d  %5d %7d %6u %s\n",depth,value,time,nodes,pv+10);
  2039.       else
  2040.         printf("    %2d  %5d %7d %6u %s\n",depth,value,time,nodes,pv);
  2041.     }
  2042.     fflush(stdout);
  2043.   }
  2044. }
  2045.  
  2046. #if defined(SMP)
  2047.  
  2048. /*
  2049. ********************************************************************************
  2050. *                                                                              *
  2051. *   CopyFromSMP() is used to copy data from a child thread to a parent thread. *
  2052. *   this only copies the appropriate parts of the TREE structure to avoid      *
  2053. *   burning memory bandwidth by copying everything.                            *
  2054. *                                                                              *
  2055. ********************************************************************************
  2056. */
  2057. void CopyFromSMP(TREE *p, TREE *c) {
  2058.   int i;
  2059.   if (c->nodes_searched && !c->stop && c->search_value > p->search_value) {
  2060.     p->pv[p->ply]=c->pv[p->ply];
  2061.     p->search_value=c->search_value;
  2062.     for (i=1;i<MAXPLY;i++) {
  2063.       p->killer_move1[i]=c->killer_move1[i];
  2064.       p->killer_move2[i]=c->killer_move2[i];
  2065.     }
  2066.   }
  2067.   p->nodes_searched+=c->nodes_searched;
  2068.   p->fail_high+=c->fail_high;
  2069.   p->fail_high_first+=c->fail_high_first;
  2070.   p->evaluations+=c->evaluations;
  2071.   p->transposition_probes+=c->transposition_probes;
  2072.   p->transposition_hits+=c->transposition_hits;
  2073.   p->pawn_probes+=c->pawn_probes;
  2074.   p->pawn_hits+=c->pawn_hits;
  2075.   p->tb_probes+=c->tb_probes;
  2076.   p->tb_probes_successful+=c->tb_probes_successful;
  2077.   p->check_extensions_done+=c->check_extensions_done;
  2078.   p->recapture_extensions_done+=c->recapture_extensions_done;
  2079.   p->passed_pawn_extensions_done+=c->passed_pawn_extensions_done;
  2080.   p->one_reply_extensions_done+=c->one_reply_extensions_done;
  2081.   c->used=0;
  2082. }
  2083.  
  2084. /*
  2085. ********************************************************************************
  2086. *                                                                              *
  2087. *   CopyToSMP() is used to copy data from a parent thread to a particular      *
  2088. *   child thread.  this only copies the appropriate parts of the TREE          *
  2089. *   structure to avoid burning memory bandwidth by copying everything.         *
  2090. *                                                                              *
  2091. ********************************************************************************
  2092. */
  2093. TREE* CopyToSMP(TREE *p) {
  2094.   int i;
  2095.   TREE *c;
  2096.   for (i=1;i<MAX_BLOCKS+1 && local[i]->used;i++);
  2097.   if (i > MAX_BLOCKS) {
  2098.     Print(128, "ERROR.  no SMP block can be allocated\n");
  2099.     return(0);
  2100.   }
  2101.   c=local[i];
  2102.   c->used=1;
  2103.   c->stop=0;
  2104.   c->done=0;
  2105.   for (i=0;i<max_threads;i++) c->siblings[i]=0;
  2106.   c->pos=p->pos;
  2107.   c->pv[p->ply-1]=p->pv[p->ply-1];
  2108.   c->pv[p->ply]=p->pv[p->ply];
  2109.   c->next_status[p->ply]=p->next_status[p->ply];
  2110.   c->save_hash_key[p->ply]=p->save_hash_key[p->ply];
  2111.   c->save_pawn_hash_key[p->ply]=p->save_pawn_hash_key[p->ply];
  2112.   c->rephead_w=c->replist_w+(p->rephead_w-p->replist_w);
  2113.   c->rephead_b=c->replist_b+(p->rephead_b-p->replist_b);
  2114.   for (i=0;i<=p->rephead_w-p->replist_w+((p->ply-1)>>1);i++)
  2115.     c->replist_w[i]=p->replist_w[i];
  2116.   for (i=0;i<=p->rephead_b-p->replist_b+((p->ply-1)>>1);i++)
  2117.     c->replist_b[i]=p->replist_b[i];
  2118.   c->last[p->ply]=c->move_list;
  2119.   c->hash_move[p->ply]=p->hash_move[p->ply];
  2120.   for (i=1;i<=p->ply;i++) {
  2121.     c->position[i]=p->position[i];
  2122.     c->current_move[i]=p->current_move[i];
  2123.     c->extended_reason[i]=p->extended_reason[i];
  2124.     c->in_check[i]=p->in_check[i];
  2125.     c->current_phase[i]=p->current_phase[i];
  2126.   }
  2127.   for (i=1;i<MAXPLY;i++) {
  2128.     c->killer_move1[i]=p->killer_move1[i];
  2129.     c->killer_move2[i]=p->killer_move2[i];
  2130.   }
  2131.   c->nodes_searched=0;
  2132.   c->fail_high=0;
  2133.   c->fail_high_first=0;
  2134.   c->evaluations=0;
  2135.   c->transposition_probes=0;
  2136.   c->transposition_hits=0;
  2137.   c->pawn_probes=0;
  2138.   c->pawn_hits=0;
  2139.   c->tb_probes=0;
  2140.   c->tb_probes_successful=0;
  2141.   c->check_extensions_done=0;
  2142.   c->recapture_extensions_done=0;
  2143.   c->passed_pawn_extensions_done=0;
  2144.   c->one_reply_extensions_done=0;
  2145.   c->alpha=p->alpha;
  2146.   c->beta=p->beta;
  2147.   c->value=p->value;
  2148.   c->wtm=p->wtm;
  2149.   c->ply=p->ply;
  2150.   c->depth=p->depth;
  2151.   c->threat=p->threat;
  2152.   c->search_value=0;
  2153.   return(c);
  2154. }
  2155.  
  2156. #endif
  2157.  
  2158. /* last modified 07/07/98 */
  2159. /*
  2160. ********************************************************************************
  2161. *                                                                              *
  2162. *   LegalMove() tests a move to confirm it is absolutely legal.  it should not *
  2163. *   be used inside the search, but can be used to check a 21-bit (compressed)  *
  2164. *   move to be sure it is safe to make it on the permanent game board.         *
  2165. *                                                                              *
  2166. ********************************************************************************
  2167. */
  2168. int LegalMove(TREE *tree, int ply, int wtm, int move) {
  2169.   int moves[220], *mv, *mvp;
  2170. /*
  2171.    generate moves, then eliminate any that are illegal.
  2172. */
  2173.   if (move == 0) return(0);
  2174.   tree->position[MAXPLY]=tree->position[ply];
  2175.   mvp=GenerateCaptures(tree,MAXPLY, wtm, moves);
  2176.   mvp=GenerateNonCaptures(tree,MAXPLY, wtm, mvp);
  2177.   for (mv=&moves[0];mv<mvp;mv++) {
  2178.     MakeMove(tree,MAXPLY, *mv, wtm);
  2179.     if (!Check(wtm) && move==*mv) {
  2180.       UnMakeMove(tree,MAXPLY, *mv, wtm);
  2181.       return(1);
  2182.     }
  2183.     UnMakeMove(tree,MAXPLY, *mv, wtm);
  2184.   }
  2185.   return(0);
  2186. }
  2187.