home *** CD-ROM | disk | FTP | other *** search
/ Dream 57 / Amiga_Dream_57.iso / Amiga / Jeux / Reflexion / Crafty-15.19.lha / crafty-15.19 / src / option.c < prev    next >
C/C++ Source or Header  |  1998-09-13  |  137KB  |  3,469 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <signal.h>
  6. #include "chess.h"
  7. #include "data.h"
  8. #if defined(UNIX) || defined(AMIGA)
  9. #  include <unistd.h>
  10. #endif
  11. #include "epdglue.h"
  12.  
  13. /* last modified 06/08/98 */
  14. /*
  15. ********************************************************************************
  16. *                                                                              *
  17. *   Option() is used to handle user input necessary to control/customize the   *
  18. *   program.  it performs all functions excepting chess move input which is    *
  19. *   handled by main().                                                         *
  20. *                                                                              *
  21. ********************************************************************************
  22. */
  23. int Option(TREE *tree)
  24. {
  25. /*
  26.  ----------------------------------------------------------
  27. |                                                          |
  28. |   EPD implementation interface code.  EPD commands can   |
  29. |   not be handled if the program is actually searching in |
  30. |   a real game, and if Crafty is "pondering" this has to  |
  31. |   be stopped.                                            |
  32. |                                                          |
  33.  ----------------------------------------------------------
  34. */
  35.   nargs=ReadParse(buffer,args,"     ;=/");
  36.   if (!nargs) return(1);
  37.   if (initialized) {
  38.     if (EGCommandCheck(buffer)) {
  39.       if (thinking || pondering) return (2);
  40.       else {
  41.         (void) EGCommand(buffer);
  42.         return (1);
  43.       }
  44.     }
  45.   }
  46. /*
  47.  ----------------------------------------------------------
  48. |                                                          |
  49. |   "." ignores "." if it happens to get to this point, if |
  50. |   xboard is running.                                     |
  51. |                                                          |
  52.  ----------------------------------------------------------
  53. */
  54.   if (OptionMatch(".",*args)) {
  55.     if (xboard) {
  56.       printf("stat01: 0 0 0 0 0\n");
  57.       fflush(stdout);
  58.       return(1);
  59.     }
  60.     else return(0);
  61.   }
  62. /*
  63.  ----------------------------------------------------------
  64. |                                                          |
  65. |   "alarm" command turns audible move warning on/off.     |
  66. |                                                          |
  67.  ----------------------------------------------------------
  68. */
  69.   else if (OptionMatch("alarm",*args)) {
  70.     RestoreGame();
  71.     if (!strcmp(args[1],"on")) audible_alarm=0x07;
  72.     else if (!strcmp(args[1],"off")) audible_alarm=0x00;
  73.     else printf("usage:  alarm on|off\n");
  74.   }
  75. /*
  76.  ----------------------------------------------------------
  77. |                                                          |
  78. |   "analyze" puts crafty in analyze mode, where it reads  |
  79. |   moves in and between moves, computes as though it is   |
  80. |   trying to find the best move to make.  when another    |
  81. |   move is entered, it switches sides and continues.  it  |
  82. |   will never make a move on its own, rather, it will     |
  83. |   continue to analyze until an "exit" command is given.  |
  84. |                                                          |
  85.  ----------------------------------------------------------
  86. */
  87.   else if (OptionMatch("analyze",*args)) {
  88.     if (thinking || pondering) return(2);
  89.     Analyze();
  90.   }
  91. /*
  92.  ----------------------------------------------------------
  93. |                                                          |
  94. |   "annotate" command is used to read a series of moves   |
  95. |   and analyze the resulting game, producing comments as  |
  96. |   requested by the user.                                 |
  97. |                                                          |
  98.  ----------------------------------------------------------
  99. */
  100.   else if (OptionMatch("annotate",*args)) {
  101.     if (thinking || pondering) return(2);
  102.     Annotate();
  103.   }
  104. /*
  105.  ----------------------------------------------------------
  106. |                                                          |
  107. |   "ansi" command turns video highlight on/off.           |
  108. |                                                          |
  109.  ----------------------------------------------------------
  110. */
  111.   else if (OptionMatch("ansi",*args)) {
  112.     if (nargs < 2) printf("usage:  ansi on|off\n");
  113.     if (!strcmp(args[1],"on")) ansi=1;
  114.     else if (!strcmp(args[1],"off")) ansi=0;
  115.   }
  116. /*
  117.  ----------------------------------------------------------
  118. |                                                          |
  119. |   "auto232" enables auto232 mode.  note that there is    |
  120. |   another alias "DR".                                    |
  121. |                                                          |
  122.  ----------------------------------------------------------
  123. */
  124.   else if (OptionMatch("auto232",*args) || OptionMatch("DR",*args)) {
  125.     if (auto_file) {
  126.       fclose(auto_file);
  127.       auto_file=0;
  128.       auto232=0;
  129.       printf("auto232 disabled\n");
  130.     }
  131.     else {
  132.       auto_file=fopen("PRN", "w");
  133.       auto232=1;
  134.       printf("auto232 enabled\n");
  135.       book_selection_width=3;
  136.       mode=tournament_mode;
  137.     }
  138.   }
  139. /*
  140.  ----------------------------------------------------------
  141. |                                                          |
  142. |   "batch" command disables asynchronous I/O so that a    |
  143. |   stream of commands can be put into a file and they are |
  144. |   not executed instantly.                                |
  145. |                                                          |
  146.  ----------------------------------------------------------
  147. */
  148.   else if (OptionMatch("batch",*args)) {
  149.     if (!strcmp(args[1],"on")) batch_mode=1;
  150.     else if (!strcmp(args[1],"off")) batch_mode=0;
  151.     else printf("usage:  batch on|off\n");
  152.   }
  153. /*
  154.  ----------------------------------------------------------
  155. |                                                          |
  156. |  "beep" command is ignored. [xboard compatibility]       |
  157. |                                                          |
  158.  ----------------------------------------------------------
  159. */
  160.   else if (OptionMatch("beep",*args)) {
  161.     return(xboard);
  162.   }
  163. /*
  164.  ----------------------------------------------------------
  165. |                                                          |
  166. |  "bench" runs internal performance benchmark             |
  167. |                                                          |
  168.  ----------------------------------------------------------
  169. */
  170.   else if (OptionMatch("bench",*args)) {
  171.     Bench();
  172.   }
  173. /*
  174.  ----------------------------------------------------------
  175. |                                                          |
  176. |  "bk"  book command from xboard sends the suggested book |
  177. |  moves.                                                  |
  178. |                                                          |
  179.  ----------------------------------------------------------
  180. */
  181.   else if (OptionMatch("bk",*args)) {
  182.     printf("\t%s\n\n",book_hint);
  183.     fflush(stdout);
  184.     return(xboard);
  185.   }
  186. /*
  187.  ----------------------------------------------------------
  188. |                                                          |
  189. |   "black" command sets black to move (ChangeSide(wtm)).             |
  190. |                                                          |
  191.  ----------------------------------------------------------
  192. */
  193.   else if (OptionMatch("black",*args)) {
  194.     if (strlen(*args) == 1) return(1);
  195.     if (thinking || pondering) return (2);
  196.     ponder_move=0;
  197.     last_pv.path_iteration_depth=0;
  198.     last_pv.path_length=0;
  199.     if (wtm) Pass();
  200.     force=0;
  201.   }
  202. /*
  203.  ----------------------------------------------------------
  204. |                                                          |
  205. |  "bogus" command is ignored. [xboard compatibility]      |
  206. |                                                          |
  207.  ----------------------------------------------------------
  208. */
  209.   else if (OptionMatch("bogus",*args)) {
  210.     return(xboard);
  211.   }
  212. /*
  213.  ----------------------------------------------------------
  214. |                                                          |
  215. |   "bookw" command updates the book selection weights.    |
  216. |                                                          |
  217.  ----------------------------------------------------------
  218. */
  219.   else if (!strcmp("bookw",*args)) {
  220.     if (nargs > 1) {
  221.       if (!strcmp("freq",args[1]))
  222.         book_weight_freq=atof(args[2]);
  223.       else if (!strcmp("eval",args[1]))
  224.         book_weight_eval=atof(args[2]);
  225.       else if (!strcmp("learn",args[1]))
  226.         book_weight_learn=atof(args[2]);
  227.     }
  228.     else {
  229.       Print(128,"frequency (freq)..............%4.2f\n",book_weight_freq);
  230.       Print(128,"static evaluation (eval)......%4.2f\n",book_weight_eval);
  231.       Print(128,"learning (learn)..............%4.2f\n",book_weight_learn);
  232.     }
  233.   }
  234. /*
  235.  ----------------------------------------------------------
  236. |                                                          |
  237. |   "book" command updates/creates the opening book file.  |
  238. |                                                          |
  239.  ----------------------------------------------------------
  240. */
  241.   else if (!strcmp("book",*args)) {
  242.     nargs=ReadParse(buffer,args,"     ;");
  243.     BookUp(tree,"book.bin", nargs-1,args+1);
  244.   }
  245.   else if (!strcmp("books",*args)) {
  246.     nargs=ReadParse(buffer,args,"     ;");
  247.     BookUp(tree,"books.bin", nargs-1,args+1);
  248.   }
  249. /*
  250.  ----------------------------------------------------------
  251. |                                                          |
  252. |   "channel" command behaves just like the whisper        |
  253. |   command, but sends the output to "channel n" instead.  |
  254. |   there is an optional second parameter that will be     |
  255. |   added to the channel tell to indicate what the tell is |
  256. |   connected to, such as when multiple GM games are going |
  257. |   on, so that the comment can be directed to a game.     |
  258. |                                                          |
  259.  ----------------------------------------------------------
  260. */
  261.   else if (OptionMatch("channel",*args)) {
  262.     int tchannel;
  263.  
  264.     nargs=ReadParse(buffer,args,"     ;");
  265.     if (nargs < 2) {
  266.       printf("usage:  channel <n> [title]\n");
  267.       return(1);
  268.     }
  269.     tchannel=atoi(args[1]);
  270.     if (tchannel) channel=tchannel;
  271.     if (nargs > 1) strcpy(channel_title,args[2]);
  272.   }
  273. /*
  274.  ----------------------------------------------------------
  275. |                                                          |
  276. |   "clock" command displays chess clock.                  |
  277. |                                                          |
  278.  ----------------------------------------------------------
  279. */
  280.   else if (OptionMatch("clock",*args)) {
  281.     if (nargs > 1)
  282.       tc_time_remaining=ParseTime(args[1])*6000;
  283.       if (tc_time_remaining <= tc_operator_time) {
  284.         Print(4095,"ERROR:  remaining time less than operator time\n");
  285.         Print(4095,"ERROR:  resetting operator time to 0:00.\n");
  286.         Print(4095,"ERROR:  use \"operator n\" command to correct after time control\n");
  287.         tc_operator_time=0;
  288.       }
  289.       
  290.     if (nargs > 2)
  291.       tc_time_remaining_opponent=ParseTime(args[2])*6000;
  292.     Print(4095,"time remaining %s (Crafty)",
  293.           DisplayHHMM(tc_time_remaining));
  294.     Print(4095,"  %s (opponent).\n",
  295.           DisplayHHMM(tc_time_remaining_opponent));
  296.     Print(4095,"%d moves to next time control (Crafty)\n",
  297.           tc_moves_remaining);
  298.   }
  299. /*
  300.  ----------------------------------------------------------
  301. |                                                          |
  302. |   "display" command displays the chess board.            |
  303. |                                                          |
  304. |   "display" command sets specific display options which  |
  305. |   control how "chatty" the program is.  in the variable  |
  306. |   display_options, the following bits are set/cleared    |
  307. |   based on the option chosen.                            |
  308. |                                                          |
  309. |     1 -> display time for moves.                         |
  310. |     2 -> display variation when it changes.              |
  311. |     4 -> display variation at end of iteration.          |
  312. |     8 -> display basic search statistics.                |
  313. |    16 -> display extended search statistics.             |
  314. |    32 -> display root moves as they are searched.        |
  315. |    64 -> display move numbers in the PV output.          |
  316. |   128 -> display general informational messages.         |
  317. |                                                          |
  318.  ----------------------------------------------------------
  319. */
  320.   else if (OptionMatch("display",*args)) {
  321.     int i;
  322.     if (nargs > 1) do {
  323.       if (OptionMatch("time",args[1])) {
  324.         display_options|=1;
  325.         Print(128,"display time for moves played in game.\n");
  326.       }
  327.       else if (OptionMatch("notime",args[1])) {
  328.         display_options&=4095-1;
  329.         Print(128,"don't display time for moves played in game.\n");
  330.       }
  331.       else if (OptionMatch("changes",args[1])) {
  332.         display_options|=2;
  333.         Print(128,"display PV each time it changes.\n");
  334.       }
  335.       else if (OptionMatch("nochanges",args[1])) {
  336.         display_options&=4095-2;
  337.         Print(128,"don't display PV each time it changes.\n");
  338.       }
  339.       else if (OptionMatch("variation",args[1])) {
  340.         display_options|=4;
  341.         Print(128,"display PV at end of each iteration.\n");
  342.       }
  343.       else if (OptionMatch("novariation",args[1])) {
  344.         display_options&=4095-4;
  345.         Print(128,"don't display PV at end of each iteration.\n");
  346.       }
  347.       else if (OptionMatch("stats",args[1])) {
  348.         display_options|=8;
  349.         Print(128,"display statistics at end of each search.\n");
  350.       }
  351.       else if (OptionMatch("nostats",args[1])) {
  352.         display_options&=4095-8;
  353.         Print(128,"don't.display statistics at end of each search.\n");
  354.       }
  355.       else if (OptionMatch("extstats",args[1])) {
  356.         display_options|=16;
  357.         Print(128,"display extended statistics at end of each search.\n");
  358.       }
  359.       else if (OptionMatch("noextstats",args[1])) {
  360.         display_options&=4095-16;
  361.         Print(128,"don't display extended statistics at end of each search.\n");
  362.       }
  363.       else if (OptionMatch("movenum",args[1])) {
  364.         display_options|=64;
  365.         Print(128,"display move numbers in variations.\n");
  366.       }
  367.       else if (OptionMatch("nomovenum",args[1])) {
  368.         display_options&=4095-64;
  369.         Print(128,"don't display move numbers in variations.\n");
  370.       }
  371.       else if (OptionMatch("moves",args[1])) {
  372.         display_options|=32;
  373.         Print(128,"display ply-1 moves as they are searched.\n");
  374.       }
  375.       else if (OptionMatch("nomoves",args[1])) {
  376.         display_options&=4095-32;
  377.         Print(128,"don't display ply-1 moves as they are searched.\n");
  378.       }
  379.       else if (OptionMatch("general",args[1])) {
  380.         display_options|=128;
  381.         Print(128,"display informational messages.\n");
  382.       }
  383.       else if (OptionMatch("nogeneral",args[1])) {
  384.         display_options&=4095-128;
  385.         Print(128,"don't display informational messages.\n");
  386.       }
  387.       else if (OptionMatch("*",args[1])) {
  388.         if (display_options&1)
  389.           printf("display time for moves\n");
  390.         if (display_options&2)
  391.           printf("display variation when it changes.\n");
  392.         if (display_options&4)
  393.           printf("display variation at end of iteration.\n");
  394.         if (display_options&8)
  395.           printf("display basic search stats.\n");
  396.         if (display_options&16)
  397.           printf("display extended search stats.\n");
  398.         if (display_options&32)
  399.           printf("display ply-1 moves as they are searched.\n");
  400.         if (display_options&64)
  401.           printf("display move numbers in variations.\n");
  402.         if (display_options&128)
  403.           printf("display general messages.\n");
  404.       }
  405.       else break;
  406.       return(1);
  407.     } while(0);
  408.     if (nargs > 1) {
  409.       if (thinking || pondering) return (2);
  410.       tree->position[1]=tree->position[0];
  411.       PreEvaluate(tree,wtm);
  412.       if (OptionMatch("pawn",args[1])) {
  413.         DisplayPieceBoards(pawn_value_w,pawn_value_b);
  414.         i=Evaluate(tree,1,1,-99999,99999);
  415.         printf(" -----------------weak-----------------");
  416.         printf("      -----------------weak-----------------\n");
  417.         for (i=128;i;i=(i>>1)) printf("%4d ",(i&tree->pawn_score.weak_w)!=0);
  418.         printf("    ");
  419.         for (i=128;i;i=(i>>1)) printf("%4d ",(i&tree->pawn_score.weak_b)!=0);
  420.         printf("\n");
  421.       }
  422.       if (OptionMatch("knight",args[1]))
  423.         DisplayPieceBoards(knight_value_w,knight_value_b);
  424.       if (OptionMatch("bishop",args[1]))
  425.         DisplayPieceBoards(bishop_value_w,bishop_value_b);
  426.       if (OptionMatch("rook",args[1]))
  427.         DisplayPieceBoards(rook_value_w,rook_value_b);
  428.       if (OptionMatch("queen",args[1]))
  429.         DisplayPieceBoards(queen_value_w,queen_value_b);
  430.       if (OptionMatch("king",args[1]))
  431.         DisplayPieceBoards(king_value_w,king_value_b);
  432.     }
  433.     else DisplayChessBoard(stdout,display);
  434.   }
  435. /*
  436.  ----------------------------------------------------------
  437. |                                                          |
  438. |   "delay" command sets a specific delay (in ms) for      |
  439. |   auto232 synchronization.                               |
  440. |                                                          |
  441.  ----------------------------------------------------------
  442. */
  443.   else if (!strcmp("delay",*args)) {
  444.     if (nargs < 2) {
  445.       printf("usage:  delay <n>\n");
  446.       return(1);
  447.     }
  448.     auto232_delay=atoi(args[1]);
  449.     Print(4095,"auto232 delay value set to %d ms.\n",auto232_delay);
  450.   }
  451. /*
  452.  ----------------------------------------------------------
  453. |                                                          |
  454. |   "depth" command sets a specific search depth to        |
  455. |   control the tree search depth. [xboard compatibility]. |
  456. |                                                          |
  457.  ----------------------------------------------------------
  458. */
  459.   else if (!strcmp("depth",*args)) {
  460.     if (nargs < 2) {
  461.       printf("usage:  depth <n>\n");
  462.       return(1);
  463.     }
  464.     search_depth=atoi(args[1]);
  465.     Print(4095,"search depth set to %d.\n",search_depth);
  466.   }
  467. /*
  468.  ----------------------------------------------------------
  469. |                                                          |
  470. |   "draw" is used to offer Crafty a draw.                 |
  471. |                                                          |
  472.  ----------------------------------------------------------
  473. */
  474.   else if (OptionMatch("draw",*args)) {
  475.     if (nargs == 1) {
  476.       int drawsc=DrawScore(1);
  477.       if (move_number<40 || !accept_draws) drawsc=-300;
  478.       if (last_search_value<=drawsc && (tc_increment!=0 ||
  479.           tc_time_remaining_opponent>=1000)) {
  480.         if (xboard) Print(4095,"tellics draw\n");
  481.         else Print(4095,"Draw accepted.\n");
  482.         Print(4095,"1/2-1/2 {Draw agreed}\n");
  483.         strcpy(pgn_result,"1/2-1/2");
  484.       }
  485.       else {
  486.         if (xboard) {
  487.           Print(4095,"tellics decline\n");
  488.           Print(4095,"Decline\n");
  489.         }
  490.         else Print(4095,"Draw declined.\n");
  491.       }
  492.     }
  493.     else {
  494.       if (!strcmp(args[1],"accept")) {
  495.         accept_draws=1;
  496.         Print(128,"accept draw offers\n");
  497.       }
  498.       else if (!strcmp(args[1],"decline")) {
  499.         accept_draws=0;
  500.         Print(128,"decline draw offers\n");
  501.       }
  502.       else Print(128,"usage: draw accept|decline\n");
  503.     }
  504.   }
  505. /*
  506.  ----------------------------------------------------------
  507. |                                                          |
  508. |   "drawscore" sets the default draw score (which is      |
  509. |    forced to zero when the endgame is reached.)          |
  510. |                                                          |
  511.  ----------------------------------------------------------
  512. */
  513.   else if (OptionMatch("drawscore",*args)) {
  514.     if (nargs < 2) {
  515.       printf("usage:  drawscore <n>\n");
  516.       return(1);
  517.     }
  518.     default_draw_score=atoi(args[1]);
  519.     printf("draw score set to %7.2f pawns.\n",
  520.            ((float) default_draw_score) / 100.0);
  521.   }
  522. /*
  523.  ----------------------------------------------------------
  524. |                                                          |
  525. |  "easy" command disables thinking on opponent's time.    |
  526. |                                                          |
  527.  ----------------------------------------------------------
  528. */
  529.   else if (OptionMatch("easy",*args)) {
  530.     ponder=0;
  531.     Print(4095,"pondering disabled.\n");
  532.   }
  533. /*
  534.  ----------------------------------------------------------
  535. |                                                          |
  536. |   "echo" command displays messages from command file.    |
  537. |                                                          |
  538.  ----------------------------------------------------------
  539. */
  540.   else if (OptionMatch("echo",*args) || OptionMatch("title",*args)) {
  541.   }
  542. /*
  543.  ----------------------------------------------------------
  544. |                                                          |
  545. |   "edit" command modifies the board position.            |
  546. |                                                          |
  547.  ----------------------------------------------------------
  548. */
  549.   else if (OptionMatch("edit",*args) && strcmp(*args,"ed")) {
  550.     if (thinking || pondering) return (2);
  551.     Edit();
  552.     move_number=1; /* discard history */
  553.     if (!wtm) {
  554.       wtm=1;
  555.       Pass();
  556.     }
  557.     ponder_move=0;
  558.     last_pv.path_iteration_depth=0;
  559.     last_pv.path_length=0;
  560.     strcpy(buffer,"savepos *");
  561.     (void) Option(tree);
  562.   }
  563. /*
  564.  ----------------------------------------------------------
  565. |                                                          |
  566. |   "egtb" command enables/disables tablebases and sets    |
  567. |   the number of pieces available for probing.            |
  568. |                                                          |
  569.  ----------------------------------------------------------
  570. */
  571.   else if (OptionMatch("egtb",*args)) {
  572.     if (nargs < 2) printf("usage:  tb <n>\n");
  573.     EGTBlimit=atoi(args[1]);
  574.     if (EGTBlimit!=0 && EGTBlimit!=4 && EGTBlimit!=5) {
  575.       Print(4095,"egtb value must be 0, 4 or 5 *only*\n");
  576.       EGTBlimit=0;
  577.     }
  578.   }
  579. /*
  580.  ----------------------------------------------------------
  581. |                                                          |
  582. |   "end" (or "quit") command terminates the program.      |
  583. |                                                          |
  584.  ----------------------------------------------------------
  585. */
  586.   else if (OptionMatch("end",*args) || OptionMatch("quit",*args)) {
  587.     if (moves_out_of_book)
  588.       LearnBook(tree,crafty_is_white,last_search_value,0,0,1);
  589.     Print(4095,"execution complete.\n");
  590.     fflush(stdout);
  591.     if (book_file) fclose(book_file);
  592.     if (books_file) fclose(books_file);
  593.     if (book_lrn_file) fclose(book_lrn_file);
  594.     if (position_file) fclose(position_file);
  595.     if (position_lrn_file) fclose(position_lrn_file);
  596.     if (history_file) fclose(history_file);
  597.     if (log_file) fclose(log_file);
  598.     EGTerm();
  599.     exit(0);
  600.   }
  601. /*
  602.  ----------------------------------------------------------
  603. |                                                          |
  604. |  "eot" command is a no-operation that is used to keep    |
  605. |  Crafty and the ICS interface in sync.                   |
  606. |                                                          |
  607.  ----------------------------------------------------------
  608. */
  609.   else if (OptionMatch("eot",*args)) {
  610.   }
  611. /*
  612.  ----------------------------------------------------------
  613. |                                                          |
  614. |   "evtest" command runs a test suite of problems and     |
  615. |   prints evaluations only.                               |
  616. |                                                          |
  617.  ----------------------------------------------------------
  618. */
  619.   else if (OptionMatch("evtest",*args)) {
  620.     if (thinking || pondering) return(2);
  621.     if (nargs < 2) {
  622.       printf("usage:  evtest <filename> [exitcnt]\n");
  623.       return(1);
  624.     }
  625.     EVTest(args[1]);
  626.     ponder_move=0;
  627.     last_pv.path_iteration_depth=0;
  628.     last_pv.path_length=0;
  629.   }
  630. /*
  631.  ----------------------------------------------------------
  632. |                                                          |
  633. |   "exit" command resets input device to STDIN.           |
  634. |                                                          |
  635.  ----------------------------------------------------------
  636. */
  637.   else if (OptionMatch("exit",*args)) {
  638.     if (analyze_mode) return(0);
  639.     if (input_stream != stdin) fclose(input_stream);
  640.     input_stream=stdin;
  641.     ReadClear();
  642.     Print(4095,"\n");
  643.   }
  644. /*
  645.  ----------------------------------------------------------
  646. |                                                          |
  647. |   "extension" command allows setting the various search  |
  648. |   extension depths to any reasonable value between 0 and |
  649. |   1.0                                                    |
  650. |                                                          |
  651.  ----------------------------------------------------------
  652. */
  653.   else if (OptionMatch("ext",*args)) {
  654.     if (nargs < 3) {
  655.       printf("usage:  ext/name=n\n");
  656.       return(1);
  657.     }
  658.     if (OptionMatch("incheck",args[1])) {
  659.       float ext=atof(args[2]);
  660.       incheck_depth=60.0*ext;
  661.       if (incheck_depth < 0) incheck_depth=0;
  662.       if (incheck_depth > 60) incheck_depth=60;
  663.     }
  664.     if (OptionMatch("onerep",args[1])) {
  665.       float ext=atof(args[2]);
  666.       onerep_depth=60.0*ext;
  667.       if (onerep_depth < 0) onerep_depth=0;
  668.       if (onerep_depth > 60) onerep_depth=60;
  669.     }
  670.     if (OptionMatch("pushpp",args[1])) {
  671.       float ext=atof(args[2]);
  672.       pushpp_depth=60.0*ext;
  673.       if (pushpp_depth < 0) pushpp_depth=0;
  674.       if (pushpp_depth > 60) pushpp_depth=60;
  675.     }
  676.     if (OptionMatch("recapture",args[1])) {
  677.       float ext=atof(args[2]);
  678.       recap_depth=60.0*ext;
  679.       if (recap_depth < 0) recap_depth=0;
  680.       if (recap_depth > 60) recap_depth=60;
  681.     }
  682.     if (OptionMatch("singular",args[1])) {
  683.       float ext=atof(args[2]);
  684.       singular_depth=60.0*ext;
  685.       if (singular_depth < 0) singular_depth=0;
  686.       if (singular_depth > 60) singular_depth=60;
  687.     }
  688.     if (OptionMatch("threat",args[1])) {
  689.       float ext=atof(args[2]);
  690.       threat_depth=60.0*ext;
  691.       if (threat_depth < 0) threat_depth=0;
  692.       if (threat_depth > 60) threat_depth=60;
  693.     }
  694.     Print(1,"one-reply extension..................%4.2f\n",(float) onerep_depth/60.0);
  695.     Print(1," in-check extension..................%4.2f\n",(float) incheck_depth/60.0);
  696.     Print(1,"recapture extension..................%4.2f\n",(float) recap_depth/60.0);
  697.     Print(1,"   pushpp extension..................%4.2f\n",(float) pushpp_depth/60.0);
  698.     Print(1,"mate thrt extension..................%4.2f\n",(float) threat_depth/60.0);
  699.     Print(1," singular extension..................%4.2f\n",(float) singular_depth/60.0);
  700.   }
  701. /*
  702.  ----------------------------------------------------------
  703. |                                                          |
  704. |   "flag" command controls whether Crafty will call the   |
  705. |   flag in xboard/winboard games (to end the game.)       |
  706. |                                                          |
  707.  ----------------------------------------------------------
  708. */
  709.   else if (!strcmp("flag",*args)) {
  710.     if (nargs < 2) {
  711.       printf("usage:  flag on|off\n");
  712.       return(1);
  713.     }
  714.     if (!strcmp(args[1],"on")) call_flag=1;
  715.     else if (!strcmp(args[1],"off")) call_flag=0;
  716.    
  717.     if (call_flag) Print(4095,"end game on time forfeits\n");
  718.     else Print(4095,"ignore time forfeits\n");
  719.   }
  720. /*
  721.  ----------------------------------------------------------
  722. |                                                          |
  723. |   "flip" command flips the board, interchanging each     |
  724. |   rank with the corresponding rank on the other half of  |
  725. |   the board, and also reverses the color of all pieces.  |
  726. |                                                          |
  727.  ----------------------------------------------------------
  728. */
  729.   else if (OptionMatch("flip",*args)) {
  730.     int file, rank, piece;
  731.     if (thinking || pondering) return(2);
  732.     for (rank=0;rank<4;rank++) {
  733.       for (file=0;file<8;file++) {
  734.         piece=-PieceOnSquare((rank<<3)+file);
  735.         PieceOnSquare((rank<<3)+file)=-PieceOnSquare(((7-rank)<<3)+file);
  736.         PieceOnSquare(((7-rank)<<3)+file)=piece;
  737.       }
  738.     }
  739.     SetChessBitBoards(&tree->position[0]);
  740.   }
  741. /*
  742.  ----------------------------------------------------------
  743. |                                                          |
  744. |   "flop" command flops the board, interchanging each     |
  745. |   file with the corresponding file on the other half of  |
  746. |   the board.                                             |
  747. |                                                          |
  748.  ----------------------------------------------------------
  749. */
  750.   else if (OptionMatch("flop",*args)) {
  751.     int file, rank, piece;
  752.     if (thinking || pondering) return(2);
  753.     for (rank=0;rank<8;rank++) {
  754.       for (file=0;file<4;file++) {
  755.         piece=PieceOnSquare((rank<<3)+file);
  756.         PieceOnSquare((rank<<3)+file)=PieceOnSquare((rank<<3)+7-file);
  757.         PieceOnSquare((rank<<3)+7-file)=piece;
  758.       }
  759.     }
  760.     SetChessBitBoards(&tree->position[0]);
  761.   }
  762. /*
  763.  ----------------------------------------------------------
  764. |                                                          |
  765. |   "force" command forces the program to make a specific  |
  766. |   move instead of its last chosen move.                  |
  767. |                                                          |
  768.  ----------------------------------------------------------
  769. */
  770.   else if (OptionMatch("force",*args)) {
  771.     int move, movenum, save_move_number;
  772.     char text[16];
  773.  
  774.     if (xboard) {
  775.       force=1;
  776.       return(3);
  777.     }
  778.     if (thinking || pondering) return (2);
  779.     if (nargs < 2) {
  780.       printf("usage:  force <move>\n");
  781.       return(1);
  782.     }
  783.     ponder_move=0;
  784.     last_pv.path_iteration_depth=0;
  785.     last_pv.path_length=0;
  786.     save_move_number=move_number;
  787.     movenum=move_number;
  788.     if (wtm) movenum--;
  789.     strcpy(text,args[1]);
  790.     sprintf(buffer,"reset %d",movenum);
  791.     wtm=ChangeSide(wtm);
  792.     (void) Option(tree);
  793.     move=InputMove(tree,text,0,wtm,0,0);
  794.     if (move) {
  795.       if (input_stream != stdin) printf("%s\n",OutputMove(tree,move,0,wtm));
  796.       fseek(history_file,((movenum-1)*2+1-wtm)*10,SEEK_SET);
  797.       fprintf(history_file,"%9s\n",OutputMove(tree,move,0,wtm));
  798.       MakeMoveRoot(tree,move,wtm);
  799.       last_pv.path_iteration_depth=0;
  800.       last_pv.path_length=0;
  801.     }
  802.     else if (input_stream == stdin) printf("illegal move.\n");
  803.     wtm=ChangeSide(wtm);
  804.     move_number=save_move_number;
  805.   }
  806. /*
  807.  ----------------------------------------------------------
  808. |                                                          |
  809. |   "go" command does nothing, except force main() to      |
  810. |   start a search.  ("move" is an alias for go).          |
  811. |                                                          |
  812.  ----------------------------------------------------------
  813. */
  814.   else if (OptionMatch("go",*args) || OptionMatch("move",*args)) {
  815.     char temp[64];
  816.     if (thinking) return(2);
  817.     if (wtm) {
  818.       if (strncmp(pgn_white,"Crafty",6)) {
  819.         strcpy(temp,pgn_white);
  820.         strcpy(pgn_white,pgn_black);
  821.         strcpy(pgn_black,temp);
  822.       }
  823.     }
  824.     else{
  825.       if (strncmp(pgn_black,"Crafty",6)) {
  826.         strcpy(temp,pgn_white);
  827.         strcpy(pgn_white,pgn_black);
  828.         strcpy(pgn_black,temp);
  829.       }
  830.     }
  831.     return(-1);
  832.   }
  833. /*
  834.  ----------------------------------------------------------
  835. |                                                          |
  836. |   "history" command displays game history (moves).       |
  837. |                                                          |
  838.  ----------------------------------------------------------
  839. */
  840.   else if (OptionMatch("history",*args)) {
  841.     int i;
  842.     char buffer[128];
  843.  
  844.     printf("    white       black\n");
  845.     for (i=0;i<(move_number-1)*2-wtm+1;i++) {
  846.       fseek(history_file,i*10,SEEK_SET);
  847.       fscanf(history_file,"%s",buffer);
  848.       if (!(i%2)) printf("%3d",i/2+1);
  849.       printf("  %-10s",buffer);
  850.       if (i%2 == 1) printf("\n");
  851.     }
  852.     if (ChangeSide(wtm))printf("  ...\n");
  853.   }
  854. /*
  855.  ----------------------------------------------------------
  856. |                                                          |
  857. |  "hard" command enables thinking on opponent's time.     |
  858. |                                                          |
  859.  ----------------------------------------------------------
  860. */
  861.   else if (OptionMatch("hard",*args)) {
  862.     ponder=1;
  863.     Print(4095,"pondering enabled.\n");
  864.   }
  865. /*
  866.  ----------------------------------------------------------
  867. |                                                          |
  868. |   "hash" command controls the transposition table size.  |
  869. |   the size can be entered in one of three ways:          |
  870. |                                                          |
  871. |      hash=nnn  where nnn is in bytes.                    |
  872. |      hash=nnnK where nnn is in K bytes.                  |
  873. |      hash=nnnM where nnn is in M bytes.                  |
  874. |                                                          |
  875. |   the only restriction is that the hash table is com-    |
  876. |   puted as follows:  one entry is 16 bytes long.  there  |
  877. |   are 4 tables, two for black, two for white, with one   |
  878. |   of each being twice the size of the other for the same |
  879. |   side.  this means that one entry in one of the small   |
  880. |   tables corresponds to two in the other, so one entry   |
  881. |   really translates to six entries.  Therefore, the size |
  882. |   that is entered is divided by 6*16, and then rounded   |
  883. |   down to the nearest power of two which is a restric-   |
  884. |   tion on the size of a single table.                    |
  885. |                                                          |
  886.  ----------------------------------------------------------
  887. */
  888.   else if (OptionMatch("hash",*args)) {
  889.     int i, new_hash_size;
  890.  
  891.     if (thinking || pondering) return(2);
  892.     if (nargs > 1) {
  893.       new_hash_size=atoi(args[1]);
  894.       if (strchr(args[1],'K') || strchr(args[1],'k')) new_hash_size*=1<<10;
  895.       if (strchr(args[1],'M') || strchr(args[1],'m')) new_hash_size*=1<<20;
  896.       if (new_hash_size < 65536) {
  897.         printf("ERROR.  Minimum hash table size is 64K bytes.\n");
  898.         return(1);
  899.       }
  900.       if (new_hash_size > 0) {
  901.         if (hash_table_size) {
  902.           free(trans_ref_wa);
  903.           free(trans_ref_wb);
  904.           free(trans_ref_ba);
  905.           free(trans_ref_bb);
  906.         }
  907.         new_hash_size/=16*6;
  908.         for (log_hash=0;log_hash<(int) (8*sizeof(int));log_hash++)
  909.           if ((1<<(log_hash+1)) > new_hash_size) break;
  910.         if (log_hash) {
  911.           hash_table_size=1<<log_hash;
  912.           trans_ref_wa=malloc(16*hash_table_size);
  913.           trans_ref_wb=malloc(16*2*hash_table_size);
  914.           trans_ref_ba=malloc(16*hash_table_size);
  915.           trans_ref_bb=malloc(16*2*hash_table_size);
  916.           if (!trans_ref_wa || !trans_ref_wb || !trans_ref_ba || !trans_ref_bb) {
  917.             printf("malloc() failed, not enough memory.\n");
  918.             free(trans_ref_wa);
  919.             free(trans_ref_wb);
  920.             free(trans_ref_ba);
  921.             free(trans_ref_bb);
  922.             hash_table_size=0;
  923.             log_hash=0;
  924.             trans_ref_wa=0;
  925.             trans_ref_wb=0;
  926.             trans_ref_ba=0;
  927.             trans_ref_bb=0;
  928.           }
  929.           hash_maska=(1<<log_hash)-1;
  930.           hash_maskb=(1<<(log_hash+1))-1;
  931.           for (i=0;i<hash_table_size;i++) {
  932.             (trans_ref_wa+i)->word1=Shiftl((BITBOARD) 7,61);
  933.             (trans_ref_wa+i)->word2=0;
  934.             (trans_ref_ba+i)->word1=Shiftl((BITBOARD) 7,61);
  935.             (trans_ref_ba+i)->word2=0;
  936.           }
  937.           for (i=0;i<2*hash_table_size;i++) {
  938.             (trans_ref_wb+i)->word1=0;
  939.             (trans_ref_wb+i)->word2=0;
  940.             (trans_ref_bb+i)->word1=0;
  941.             (trans_ref_bb+i)->word2=0;
  942.           }
  943.         }
  944.         else {
  945.           trans_ref_wa=0;
  946.           trans_ref_wb=0;
  947.           trans_ref_ba=0;
  948.           trans_ref_bb=0;
  949.           hash_table_size=0;
  950.           log_hash=0;
  951.         }
  952.       }
  953.       else Print(4095,"ERROR:  hash table size must be > 0\n");
  954.     }
  955.     if (hash_table_size*6*sizeof(HASH_ENTRY) < 1<<20)
  956.       Print(4095,"hash table memory = %dK bytes.\n",
  957.             hash_table_size*6*sizeof(HASH_ENTRY)/(1<<10));
  958.     else {
  959.       if (hash_table_size*6*sizeof(HASH_ENTRY)%(1<<20))
  960.         Print(4095,"hash table memory = %.1fM bytes.\n",
  961.               (float) hash_table_size*6*sizeof(HASH_ENTRY)/(1<<20));
  962.       else
  963.         Print(4095,"hash table memory = %dM bytes.\n",
  964.               hash_table_size*6*sizeof(HASH_ENTRY)/(1<<20));
  965.     }
  966.   }
  967. /*
  968.  ----------------------------------------------------------
  969. |                                                          |
  970. |   "hashp" command controls the pawn hash table size.     |
  971. |                                                          |
  972.  ----------------------------------------------------------
  973. */
  974.   else if (OptionMatch("hashp",*args)) {
  975.     int i, new_hash_size;
  976.  
  977.     if (thinking || pondering) return(2);
  978.     if (nargs > 1) {
  979.       new_hash_size=atoi(args[1]);
  980.       if (strchr(args[1],'K') || strchr(args[1],'k')) new_hash_size*=1<<10;
  981.       if (strchr(args[1],'M') || strchr(args[1],'m')) new_hash_size*=1<<20;
  982.       if (new_hash_size > 0) {
  983.         if (pawn_hash_table) {
  984.           free(pawn_hash_table);
  985.           pawn_hash_table_size=0;
  986.           log_pawn_hash=0;
  987.           pawn_hash_table=0;
  988.         }
  989.         new_hash_size/=sizeof(PAWN_HASH_ENTRY);
  990.         for (log_pawn_hash=0;
  991.              log_pawn_hash<(int) (8*sizeof(int));
  992.              log_pawn_hash++)
  993.           if ((1<<(log_pawn_hash+1)) > new_hash_size) break;
  994.         pawn_hash_table_size=1<<log_pawn_hash;
  995.         pawn_hash_table=malloc(sizeof(PAWN_HASH_ENTRY)*pawn_hash_table_size);
  996.         if (!pawn_hash_table) {
  997.           printf("malloc() failed, not enough memory.\n");
  998.           free(pawn_hash_table);
  999.           pawn_hash_table_size=0;
  1000.           log_pawn_hash=0;
  1001.           pawn_hash_table=0;
  1002.         }
  1003.         pawn_hash_mask=((unsigned int) 037777777777)>>(32-log_pawn_hash);
  1004.         for (i=0;i<pawn_hash_table_size;i++) {
  1005.           (pawn_hash_table+i)->key=0;
  1006.           (pawn_hash_table+i)->p_score=0;
  1007.           (pawn_hash_table+i)->black_protected=0;
  1008.           (pawn_hash_table+i)->white_protected=0;
  1009.           (pawn_hash_table+i)->black_pof=0;
  1010.           (pawn_hash_table+i)->white_pof=0;
  1011.           (pawn_hash_table+i)->weak_b=0;
  1012.           (pawn_hash_table+i)->weak_w=0;
  1013.           (pawn_hash_table+i)->black_defects_k=0;
  1014.           (pawn_hash_table+i)->black_defects_q=0;
  1015.           (pawn_hash_table+i)->white_defects_k=0;
  1016.           (pawn_hash_table+i)->white_defects_q=0;
  1017.           (pawn_hash_table+i)->passed_w=0;
  1018.           (pawn_hash_table+i)->passed_w=0;
  1019.           (pawn_hash_table+i)->outside=0;
  1020.         }
  1021.       }
  1022.       else Print(4095,"ERROR:  pawn hash table size must be > 0\n");
  1023.     }
  1024.     if (pawn_hash_table_size*sizeof(PAWN_HASH_ENTRY) < 1<<20)
  1025.       Print(4095,"pawn hash table memory = %dK bytes.\n",
  1026.             pawn_hash_table_size*sizeof(PAWN_HASH_ENTRY)/(1<<10));
  1027.     else {
  1028.       if (pawn_hash_table_size*sizeof(PAWN_HASH_ENTRY)%(1<<20))
  1029.         Print(4095,"pawn hash table memory = %.1fM bytes.\n",
  1030.               (float) pawn_hash_table_size*sizeof(PAWN_HASH_ENTRY)/(1<<20));
  1031.       else
  1032.         Print(4095,"pawn hash table memory = %dM bytes.\n",
  1033.               pawn_hash_table_size*sizeof(PAWN_HASH_ENTRY)/(1<<20));
  1034.     }
  1035.   }
  1036. /*
  1037.  ----------------------------------------------------------
  1038. |                                                          |
  1039. |   "help" command lists commands/options.                 |
  1040. |                                                          |
  1041.  ----------------------------------------------------------
  1042. */
  1043.   else if (OptionMatch("help",*args)) {
  1044.     if (nargs > 1) {
  1045.       if (!strcmp("analyze",args[1])) {
  1046.         printf("analyze\n");
  1047.         printf("the analyze command puts Crafty into a mode where it will\n");
  1048.         printf("search forever in the current position.  when a move is\n");
  1049.         printf("entered, crafty will make that move, switch sides, and\n");
  1050.         printf("again compute, printing analysis as it searches.  you can\n");
  1051.         printf("back up a move by entering \"back\" or you can back up\n");
  1052.         printf("several moves by entering \"back <n>\".  note that <n> is\n");
  1053.         printf("the number of moves, counting each player's move as one.\n");
  1054.       }
  1055.       else if (!strcmp("annotate",args[1])) {
  1056.         printf("annotate filename b|w|bw moves margin time [n]\n");
  1057.         printf("where filename is the input file with game moves, while the\n");
  1058.         printf("output will be written to filename.can.  the input file is\n");
  1059.         printf("PGN-compatible with one addition, the ability to request that\n");
  1060.         printf("alternative moves also be analyzed at any point.  to do this\n");
  1061.         printf("at the point where you have alternative moves, simply include\n");
  1062.         printf("them in braces {move1, move2}, and Crafty will then search\n");
  1063.         printf("them also. b/w/bw indicates whether to annotate only the white\n");
  1064.         printf("side (w), the black side (b) or both (bw).  moves indicates\n");
  1065.         printf("which moves to annotate.  a single value says start at the\n");
  1066.         printf("indicated move and go through the entire game.  a range (20-30)\n");
  1067.         printf("annoates the given range only. margin is the difference between\n");
  1068.         printf("the search value for the move played in the game, and the best move\n");
  1069.         printf("crafty found, before a comment is generated (pawn=1.0).  time is\n");
  1070.         printf("the time limit per move in seconds.  if the optional \"n\" is\n");
  1071.         printf("appended, this produces N best moves/scores/PV's, rather than\n");
  1072.         printf("just the very best move.  it won't display any move that is worse\n");
  1073.         printf("than the actual game move played, but you can use -N to force\n");
  1074.         printf("Crafty to produce N PV's regardless of how bad they get.\n");
  1075.       }
  1076.       else if (!strcmp("book",args[1])) {
  1077.         printf("you can use the following commands to customize how the\n");
  1078.         printf("program uses the opening book(book.bin and books.bin).\n");
  1079.         printf("typically, book.bin contains a large opening database made\n");
  1080.         printf("from GM games.  books.bin is a short, customized book that\n");
  1081.         printf("contains selected lines that are well-suited to Crafty's\n");
  1082.         printf("style of play.  the <flags> can further refine how this\n");
  1083.         printf("small book file is used to encourage/avoid specific lines.\n");
  1084.         printf("book[s] create [<filename>] [maxply] [mp] [wpc]...creates a\n");
  1085.         printf("   new book by first removing the old book.bin.  it then\n");
  1086.         printf("   will parse <filename> and add the moves to book.bin (if\n");
  1087.         printf("   the book create command was used) or to books.bin (if the\n");
  1088.         printf("   books create command was used.)  <maxply> truncates book\n");
  1089.         printf("   lines after that many plies (typically 60).  <mp> will \n");
  1090.         printf("   exclude *any* move not appearing <mp> times in the input.\n");
  1091.         printf("   <wpc> is the winning percentage.  50 means exclude any\n");
  1092.         printf("   book move that doesn't have at least 50%% as many wins as\n");
  1093.         printf("   losses.\n");
  1094.         printf("book mask accept <chars>...............sets the accept mask to\n");
  1095.         printf("   the flag characters in <chars> (see flags below.)  any flags\n");
  1096.         printf("   set in this mask will include either (a) moves with the \n");
  1097.         printf("   flag set, or (b) moves with no flags set.\n");
  1098.         printf("more...");
  1099.         fflush(stdout);
  1100.         (void) Read(1,buffer);
  1101.         printf("book mask reject <chars>...............sets the reject mask to\n");
  1102.         printf("   the flag characters in <chars> (see flags below.)  any flags\n");
  1103.         printf("   set in this mask will reject any moves with the flag\n");
  1104.         printf("   set (in the opening book.)\n");
  1105.         printf("book off...............................turns the book completely off.\n");
  1106.         printf("book random 0|1........................disables/enables randomness.\n");
  1107.         printf("bookw weight <v>.......................sets weight for book ordering.\n");
  1108.         printf("   (weights are freq (frequency), eval (evaluation)\n");
  1109.         printf("   and learn (learned scores).\n");
  1110.         printf("book width n...........................specifies how many moves from\n");
  1111.         printf("   the sorted set of book moves are to be considered.  1 produces\n");
  1112.         printf("   the best move from the set, but provides little randomness.\n");
  1113.         printf("   99 includes all moves in the book move set.\n");
  1114.         printf("more...");
  1115.         fflush(stdout);
  1116.         (void) Read(1,buffer);
  1117.         printf("flags are one (or more) members of the following set of\n");
  1118.         printf("characters:  {?? ? = ! !! 0 1 2 3 4 5 6 7 8 9 A B C D E F}\n");
  1119.         printf("normally, ?? means never play, ? means rarely play,\n");
  1120.         printf("= means drawish opening, ! means good move, !! means always\n");
  1121.         printf("play, and 0-F are user flags that a user can add to any\n");
  1122.         printf("move in the book, and by setting the right mask (above) can\n");
  1123.         printf("force the program to either always play the move or never\n");
  1124.         printf("play the move.  the special character * means all flags\n");
  1125.         printf("and is probably dangerous to use.\n");
  1126.         printf("flags are added to a move by entering the move, a / or \\\n");
  1127.         printf("followed by the flags.  / means add the flags to the move\n");
  1128.         printf("preserving other flags already there while \\ means replace\n");
  1129.         printf("any flags with those following the \\.\n");
  1130.         printf("the format of the book text (raw data) is as follows:\n");
  1131.         printf("[title information] (required)\n");
  1132.         printf("e4 e5 ... (a sequence of moves)\n");
  1133.         printf("[title information for next line] (required)\n");
  1134.         printf("e4 e6 ...\n");
  1135.         printf("end (optional)\n");
  1136.         printf("\n");
  1137.       }
  1138.       else if (!strcmp("display",args[1])) {
  1139.         printf("display changes   -> display variation when it changes.\n");
  1140.         printf("display extstats  -> display search extension statistics.\n");
  1141.         printf("display hashstats -> display search hashing statistics.\n");
  1142.         printf("display movenum   -> display move numbers in PV.\n");
  1143.         printf("display moves     -> display moves as they are searched.\n");
  1144.         printf("display stats     -> display basic search statistics.\n");
  1145.         printf("display time      -> display time for moves.\n");
  1146.         printf("display variation -> display variation at end of iteration.\n");
  1147.       }
  1148.       else if (OptionMatch("edit",args[1])) {
  1149.         printf("edit is used to set up or modify a board position.  it \n");
  1150.         printf("recognizes 4 \"commands\" that it uses to alter/set up the\n");
  1151.         printf("board position (with appropriate aliases to interface with\n");
  1152.         printf("x\n");
  1153.         printf("\n");
  1154.         printf("# command causes edit to clear the chess board\n");
  1155.         printf("c command causes edit to toggle piece color.\n");
  1156.         printf("white command causes edit to place white pieces on the\n");
  1157.         printf("board; black command causes edit to place black pieces on\n");
  1158.         printf("the \n");
  1159.         printf("end (\".\" for xboard) causes edit to exit.\n");
  1160.         printf("\n");
  1161.         printf("three strings of the form [piece][file][rank] will\n");
  1162.         printf("place a [piece] on square [file][rank].  the color is set\n");
  1163.         printf("by the previous white/black command.  ex:  Ke8 puts a king\n");
  1164.         printf("on square e8\n");
  1165.         printf("\n");
  1166.       }
  1167.       else if (OptionMatch("list",args[1])) {
  1168.         printf("list is used to update the GM/IM/computer lists, which are\n");
  1169.         printf("used internally to control how crafty uses the opening book.\n");
  1170.         printf("Syntax:  list GM|IM|C [+|-name] ...\n");
  1171.         printf("   GM/IM/C selects the appropriate list.  if no name is given,\n");
  1172.         printf("the list is displayed.  if a name is given, it must be preceeded\n");
  1173.         printf("by a + (add to list) or -(remove from list).  note that this\n");
  1174.         printf("list is not saved in a file, so that anything added or removed\n");
  1175.         printf("will be lost when Crafty is re-started.  To solve this, these\n");
  1176.         printf("commands can be added to the .craftyrc file.\n");
  1177.       }
  1178.       else if (OptionMatch("pgn",args[1])) {
  1179.         printf("the pgn command is used to set the various PGN headers\n");
  1180.         printf("which are printed at the top of a PGN file produced by the\n");
  1181.         printf("savegame command.\n");
  1182.         printf("options are Event, Site, Round, White, WhiteElo, Black,\n");
  1183.         printf("BlackElo, and Result.  each is followed by the appropriate\n");
  1184.         printf("value.  most of these should likely be placed in the\n");
  1185.         printf("crafty.rc/.craftyrc file since they will be constant for a\n");
  1186.         printf("complete event.\n");
  1187.       }
  1188.       else if (OptionMatch("setboard",args[1])) {
  1189.         printf("sb is used to set up the board in any position desired.  it\n");
  1190.         printf("uses a forsythe-like string of characters to describe the\n");
  1191.         printf("board position.\n");
  1192.         printf("the standard piece codes p,n,b,r,q,k are used to denote the\n");
  1193.         printf("piece on a square, upper/lower case is used to indicate the\n");
  1194.         printf("color (WHITE/black) of the piece.\n");
  1195.         printf("\n");
  1196.         printf("the pieces are entered with the ranks on the black side of\n");
  1197.         printf("the board entered first, and the ranks on the white side\n");
  1198.         printf("entered last (ie rank 8 through rank 1).  empty squares, \n");
  1199.         printf("a number between 1 and 8 to indicate how many adjacent\n");
  1200.         printf("squares are empty.  use a / to terminate each rank after\n");
  1201.         printf("all pieces for that rank have been entered.\n");
  1202.         printf("\n");
  1203.         printf("more...");
  1204.         fflush(stdout);
  1205.         (void) Read(1,buffer);
  1206.         printf("the following input will setup the board position that\n");
  1207.         printf("is given below:\n");
  1208.         printf("\n");
  1209.         printf("                  K2R/PPP////q/5ppp/7k/ b\n");
  1210.         printf("\n");
  1211.         printf("this assumes that k represents a white king and -q\n");
  1212.         printf("represents a black queen.\n");
  1213.         printf("\n");
  1214.         printf("                   k  *  *  r  *  *  *  *\n");
  1215.         printf("                   p  p  p  *  *  *  *  *\n");
  1216.         printf("                   *  *  *  *  *  *  *  *\n");
  1217.         printf("                   *  *  *  *  *  *  *  *\n");
  1218.         printf("                   *  *  *  *  *  *  *  *\n");
  1219.         printf("                  -q  *  *  *  *  *  *  *\n");
  1220.         printf("                   *  *  *  *  * -p -p -p\n");
  1221.         printf("                   *  *  *  *  *  *  * -k\n");
  1222.         printf("\n");
  1223.         printf("the character after the final / should be either b or w to\n");
  1224.         printf("indicate the side to move.  after this side-to-move field\n");
  1225.         printf("any of the following characters can appear to indicate the\n");
  1226.         printf("following:  KQ: white can castle kingside/queenside/both;\n");
  1227.         printf("kq: same for black;  a1-h8: indicates the square occupied\n");
  1228.         printf("by a pawn that can be captured en passant.\n");
  1229.       }
  1230.       else if (!strcmp("test",args[1])) {
  1231.         printf("test <filename> [N]\n");
  1232.         printf("test is used to run a suite of \"crafty format\"\n");
  1233.         printf("test positions in a batch run.  <filename> is the\n");
  1234.         printf("name of the file in crafty test format.  [N] is an\n");
  1235.         printf("optional paremeter that is used to shorten the test\n");
  1236.         printf("time.  If crafty likes the solution move for [N]\n");
  1237.         printf("consecutive iterations, it will stop searching that\n");
  1238.         printf("position and consider it correct.  This makes a Win At\n");
  1239.         printf("Chess 60 second run take under 1/2 hour, for example.\n");
  1240.         printf("the \"crafty format\" requires three lines per position.\n");
  1241.         printf("The first line must be a \"title\" line and is used to\n");
  1242.         printf("identify each position.  The second line is a \"setboard\"\n");
  1243.         printf("command to set the position.  The third line is a line that\n");
  1244.         printf("begins with \"solution\", and then is followed by one or\n");
  1245.         printf("more solution moves.  If a position is correct only if a\n");
  1246.         printf("particular move or moves is *not* played, enter the move\n");
  1247.         printf("followed by a \"?\?, as in Nf3?, which means that this\n");
  1248.         printf("position will be counted as correct only if Nf3 is not\n");
  1249.         printf("played.\n");
  1250.       }
  1251.       else if (!strcmp("time",args[1])) {
  1252.         printf("time controls whether the program uses cpu time or\n");
  1253.         printf("wall-clock time for timing.  for tournament play,\n");
  1254.         printf("it is safer to use wall-clock timing, for testing it\n");
  1255.         printf("may be more consistent to use cpu timing if the\n");
  1256.         printf("machine is used for other things concurrently with the\n");
  1257.         printf("tests being run.\n");
  1258.         printf("\n");
  1259.         printf("time is also used to set the basic search timing\n");
  1260.         printf("controls.  the general form of the command is as\n");
  1261.         printf("follows:\n");
  1262.         printf("\n");
  1263.         printf("      time nmoves/ntime/[nmoves/ntime]/[increment]\n");
  1264.         printf("\n");
  1265.         printf("nmoves/ntime represents a traditional first time\n");
  1266.         printf("control when nmoves is an integer representing the\n");
  1267.         printf("number of moves and ntime is the total time allowed\n");
  1268.         printf("for these moves.  the [optional] nmoves/ntime is a\n");
  1269.         printf("traditional secondary time control.  increment is a\n");
  1270.         printf("feature related to ics play and emulates the fischer\n");
  1271.         printf("clock where <increment> is added to the time left\n");
  1272.         printf("after each move is made.\n");
  1273.         printf("\n");
  1274.         printf("as an alternative, nmoves can be \"sd\" which represents\n");
  1275.         printf("a sudden death time control of the remainder of the\n");
  1276.         printf("game played in ntime.  the optional secondary time\n");
  1277.         printf("control can be a sudden-death time control, as in the\n");
  1278.         printf("following example:\n");
  1279.         printf("\n");
  1280.         printf("        time 60/30/sd/30\n");
  1281.         printf("\n");
  1282.         printf("this sets 60 moves in 30 minutes, then game in 30\n");
  1283.         printf("additional minutes.  an increment can be added if\n");
  1284.         printf("desired.\n");
  1285.       }
  1286.       else printf("no help available for that command\n");
  1287.     }
  1288.     else {
  1289.       printf("alarm on|off..............turns audible alarm on/off.\n");
  1290.       printf("analyze...................analyze a game in progress\n");
  1291.       printf("annotate..................annotate game [help].\n");
  1292.       printf("ansi......................toggles reverse video highlighting.\n");
  1293.       printf("bench.....................runs performance benchmark.\n");
  1294.       printf("book......................controls book [help].\n");
  1295.       printf("black.....................sets black to move.\n");
  1296.       printf("clock.....................displays chess clock.\n");
  1297.       printf("display...................displays chess board\n");
  1298.       printf("display <n>...............sets display options [help]\n");
  1299.       printf("draw <n>..................sets default draw score.\n");
  1300.       printf("echo......................echos output to display.\n");
  1301.       printf("edit......................edit board position. [help]\n");
  1302.       printf("epdhelp...................info about EPD facility.\n");
  1303.       printf("egtb n....................set number of pieces for EGTB probes\n");
  1304.       printf("end.......................terminates program.\n");
  1305.       printf("exit......................restores STDIN to key\n");
  1306.       printf("force <move>..............forces specific move.\n");
  1307.       printf("help [command]............displays help.\n");
  1308.       printf("hash n....................sets transposition table size\n");
  1309.       printf("                          (n bytes, nK bytes or nM bytes)\n");
  1310.       printf("hashp n...................sets pawn hash table size\n");
  1311.       printf("history...................display game moves.\n");
  1312.       printf("import <filename>.........imports learning data (.lrn files).\n");
  1313.       printf("info......................displays program settings.\n");
  1314.       printf("more...");
  1315.       fflush(stdout);
  1316.       (void) Read(1,buffer);
  1317.       printf("input <filename> [title]..sets STDIN to <filename>.\n");
  1318.       printf("                          (and positions to [title] record.)\n");
  1319.       printf("kibitz <n>................sets kibitz mode <n> on ICS.\n");
  1320.       printf("level <m> <t> <i>.........sets ICS time controls.\n");
  1321.       printf("learn <n>.................enables/disables learning.\n");
  1322.       printf("list                      update/display GM/IM/computer lists.\n");
  1323.       printf("load <file> <title>       load a position from problem file.\n");
  1324.       printf("log on|off................turn logging on/off.\n");
  1325.       printf("mode normal|tournament....toggles tournament mode.\n");
  1326.       printf("move......................initiates search (same as go).\n");
  1327. # if defined(SMP)
  1328.       printf("mt n......................sets max parallel threads to use.\n");
  1329.       printf("mtmin n...................don't thread last n plies.\n");
  1330.       printf("mtmax n...................keep threads within n plies.\n");
  1331. # endif
  1332.       printf("name......................sets opponent's name.\n");
  1333.       printf("new.......................initialize and start new game.\n");
  1334.       printf("noise n...................no status until n nodes searched.\n");
  1335.       printf("operator <minutes>........allocates operator time.\n");
  1336.       printf("perf......................times the move generator/make_move.\n");
  1337.       printf("perft.....................tests the move generator/make_move.\n");
  1338.       printf("pgn option value..........set PGN header information. [help]\n");
  1339.       printf("ponder on|off.............toggle pondering off/on.\n");
  1340.       printf("ponder move...............ponder \"move\" as predicted move.\n");
  1341.       printf("read <filename>...........read moves in [from <filename>].\n");
  1342.       printf("reada <filename>..........read moves in [from <filename>].\n");
  1343.       printf("                          (appends to current game history.)\n");
  1344.       printf("reset n...................reset game to move n.\n");
  1345.       printf("resign <m> <n>............set resign threshold to <m> pawns.\n");
  1346.       printf("                          <n> = # of moves before resigning.\n");
  1347.       printf("more...");
  1348.       fflush(stdout);
  1349.       (void) Read(1,buffer);
  1350.       printf("savegame <filename>.......saves game in PGN format.\n");
  1351.       printf("savepos <filename>........saves position in FEN string.\n");
  1352.       printf("score.....................print evaluation of position.\n");
  1353.       printf("sd n......................sets absolute search depth.\n");
  1354.       printf("search <move>.............search specified move only.\n");
  1355.       printf("setboard <FEN>............sets board position to FEN position. [help]\n");
  1356.       printf("settc.....................set time controls.\n");
  1357.       printf("show book.................toggle book statistics.\n");
  1358.       printf("st n......................sets absolute search time.\n");
  1359.       printf("test <file> [N]...........test a suite of problems. [help]\n");
  1360.       printf("time......................time controls. [help]\n");
  1361.       printf("trace n...................display search tree below depth n.\n");
  1362.       printf("usage <percentage>........adjusts crafty's time usage up or down.\n");
  1363.       printf("whisper n.................sets ICS whisper mode n.\n");
  1364.       printf("wild n....................sets ICS wild position (7 for now)\n");
  1365.       printf("white.....................sets white to move.\n");
  1366.       printf("xboard....................sets xboard compatibility mode.\n");
  1367.     }
  1368.   }
  1369. /*
  1370.  ----------------------------------------------------------
  1371. |                                                          |
  1372. |   "hint" displays the expected move based on the last    |
  1373. |   search done. [xboard compatibility]                    |
  1374. |                                                          |
  1375.  ----------------------------------------------------------
  1376. */
  1377.   else if (!strcmp("hint",*args)) {
  1378.     if (strlen(hint)) {
  1379.       printf("Hint: %s\n",hint);
  1380.       fflush(stdout);
  1381.     }
  1382.   }
  1383. /*
  1384.  ----------------------------------------------------------
  1385. |                                                          |
  1386. |  "ics" command is normally invoked from main() via the   |
  1387. |  ics command-line option.  it sets proper defaults for   |
  1388. |  defaults for the custom crafty/ics interface program.   |
  1389. |                                                          |
  1390.  ----------------------------------------------------------
  1391. */
  1392.   else if (OptionMatch("ics",*args)) {
  1393.     ics=1;
  1394.     display_options&=4095-32;
  1395.   }
  1396. /*
  1397.  ----------------------------------------------------------
  1398. |                                                          |
  1399. |   "import" <filename> command is used to import a .lrn   |
  1400. |   file (either book.lrn or position.lrn) and store the   |
  1401. |   results in crafty's binary files (book.bin or          |
  1402. |   position.bin) just as though it had learned those      |
  1403. |   results by itself.                                     |
  1404. |                                                          |
  1405.  ----------------------------------------------------------
  1406. */
  1407.   else if (OptionMatch("import",*args)) {
  1408.     if (thinking || pondering) return(2);
  1409.     nargs=ReadParse(buffer,args,"     ;=");
  1410.     if (nargs < 2) printf("usage:  import <filename> [clear]\n");
  1411.     else LearnImport(tree,nargs-1,args+1);
  1412.   }
  1413. /*
  1414.  ----------------------------------------------------------
  1415. |                                                          |
  1416. |   "input" command directs the program to read input from |
  1417. |   a file until eof is reached or an "exit" command is    |
  1418. |   encountered while reading the file.                    |
  1419. |                                                          |
  1420.  ----------------------------------------------------------
  1421. */
  1422.   else if (OptionMatch("input",*args)) {
  1423.     if (thinking || pondering) return(2);
  1424.     nargs=ReadParse(buffer,args,"     =");
  1425.     if (nargs < 2) {
  1426.       printf("usage:  input <filename>\n");
  1427.       return(1);
  1428.     }
  1429.     if (!(input_stream=fopen(args[1],"r"))) {
  1430.       printf("file does not exist.\n");
  1431.       input_stream=stdin;
  1432.     }
  1433.   }
  1434. /*
  1435.  ----------------------------------------------------------
  1436. |                                                          |
  1437. |  "info" command gives some information about Crafty.     |
  1438. |                                                          |
  1439.  ----------------------------------------------------------
  1440. */
  1441.   else if (OptionMatch("info",*args)) {
  1442.     Print(4095,"Crafty version %s\n",version);
  1443.     if (hash_table_size*6*sizeof(HASH_ENTRY) < 1<<20)
  1444.       Print(4095,"hash table memory = %dK bytes.\n",
  1445.             hash_table_size*6*sizeof(HASH_ENTRY)/(1<<10));
  1446.     else {
  1447.       if (hash_table_size*6*sizeof(HASH_ENTRY)%(1<<20))
  1448.         Print(4095,"hash table memory = %.1fM bytes.\n",
  1449.               (float) hash_table_size*6*sizeof(HASH_ENTRY)/(1<<20));
  1450.       else
  1451.         Print(4095,"hash table memory = %dM bytes.\n",
  1452.               hash_table_size*6*sizeof(HASH_ENTRY)/(1<<20));
  1453.     }
  1454.     if (pawn_hash_table_size*sizeof(PAWN_HASH_ENTRY) < 1<<20)
  1455.       Print(4095,"pawn hash table memory = %dK bytes.\n",
  1456.             pawn_hash_table_size*sizeof(PAWN_HASH_ENTRY)/(1<<10));
  1457.     else {
  1458.       if (pawn_hash_table_size*6*sizeof(PAWN_HASH_ENTRY)%(1<<20))
  1459.         Print(4095,"pawn hash table memory = %.1fM bytes.\n",
  1460.               (float) pawn_hash_table_size*sizeof(PAWN_HASH_ENTRY)/(1<<20));
  1461.       else
  1462.         Print(4095,"hash table memory = %dM bytes.\n",
  1463.               pawn_hash_table_size*sizeof(PAWN_HASH_ENTRY)/(1<<20));
  1464.     }
  1465.     if (!tc_sudden_death) {
  1466.       Print(4095,"%d moves/%d minutes %d seconds primary time control\n",
  1467.             tc_moves, tc_time/6000, (tc_time/100)%60);
  1468.       Print(4095,"%d moves/%d minutes %d seconds secondary time control\n",
  1469.             tc_secondary_moves, tc_secondary_time/6000,
  1470.             (tc_secondary_time/100)%60);
  1471.       if (tc_increment) Print(4095,"increment %d seconds.\n",tc_increment/100);
  1472.     }
  1473.     else if (tc_sudden_death == 1) {
  1474.       Print(4095," game/%d minutes primary time control\n", tc_time/100);
  1475.       if (tc_increment) Print(4095,"increment %d seconds.\n",(tc_increment/100)%60);
  1476.     }
  1477.     else if (tc_sudden_death == 2) {
  1478.       Print(4095,"%d moves/%d minutes primary time control\n",
  1479.             tc_moves, tc_time/6000);
  1480.       Print(4095,"game/%d minutes secondary time control\n",
  1481.             tc_secondary_time/6000);
  1482.       if (tc_increment) Print(4095,"increment %d seconds.\n",tc_increment/100);
  1483.     }
  1484.   }
  1485. /*
  1486.  ----------------------------------------------------------
  1487. |                                                          |
  1488. |   "kibitz" command sets kibitz mode for ICS.  =1 will    |
  1489. |   kibitz mate announcements, =2 will kibitz scores and   |
  1490. |   other info, =3 will kibitz scores and PV, =4 adds the  |
  1491. |   list of book moves, =5 displays the PV after each      |
  1492. |   iteration completes, and =6 displays the PV each time  |
  1493. |   it changes in an iteration.                            |
  1494. |                                                          |
  1495.  ----------------------------------------------------------
  1496. */
  1497.   else if (OptionMatch("kibitz",*args)) {
  1498.     if (nargs < 2) {
  1499.       printf("usage:  kibitz <level>\n");
  1500.       return(1);
  1501.     }
  1502.     kibitz=atoi(args[1]);
  1503.   }
  1504. /*
  1505.  ----------------------------------------------------------
  1506. |                                                          |
  1507. |   "learn" command enables/disables the learning          |
  1508. |   algorithms used in crafty.  these are controlled by    |
  1509. |   a single variable with multiple boolean switches in    |
  1510. |   it as defined below:                                   |
  1511. |                                                          |
  1512. |   000 -> no learning enabled.                            |
  1513. |   001 -> learn which book moves are good and bad.        |
  1514. |   010 -> learn middlegame positions.                     |
  1515. |   100 -> learn from game "results" (win/lose).           |
  1516. |                                                          |
  1517. |   these are entered as an integer, which is formed by    |
  1518. |   adding the integer values 1,2,4 to enable the various  |
  1519. |   forms of learning.                                     |
  1520. |                                                          |
  1521.  ----------------------------------------------------------
  1522. */
  1523.   else if (OptionMatch("learn",*args)) {
  1524.     if (nargs == 2) learning=atoi(args[1]);
  1525.     if (learning&book_learning)
  1526.       Print(4095,"book learning enabled\n");
  1527.     else
  1528.       Print(4095,"book learning disabled\n");
  1529.     if (learning&result_learning)
  1530.       Print(4095,"result learning enabled\n");
  1531.     else
  1532.       Print(4095,"result learning disabled\n");
  1533.     if (learning&position_learning)
  1534.       Print(4095,"position learning enabled\n");
  1535.     else
  1536.       Print(4095,"position learning disabled\n");
  1537.   }
  1538. /*
  1539.  ----------------------------------------------------------
  1540. |                                                          |
  1541. |   "level" command sets time controls [ics/xboard         |
  1542. |   compatibility.]                                        |
  1543. |                                                          |
  1544.  ----------------------------------------------------------
  1545. */
  1546.   else if (OptionMatch("level",*args)) {
  1547.     if (nargs < 4) {
  1548.       printf("usage:  level <nmoves> <stime> <inc>\n");
  1549.       return(1);
  1550.     }
  1551.     tc_moves=atoi(args[1]);
  1552.     tc_time=atoi(args[2])*100;
  1553.     tc_increment=atoi(args[3])*100;
  1554.     tc_time_remaining=tc_time;
  1555.     tc_time_remaining_opponent=tc_time;
  1556.     if (!tc_moves) {
  1557.       tc_sudden_death=1;
  1558.       tc_moves=1000;
  1559.       tc_moves_remaining=1000;
  1560.     }
  1561.     else tc_sudden_death=0;
  1562.     if (tc_moves) {
  1563.       tc_secondary_moves=tc_moves;
  1564.       tc_secondary_time=tc_time;
  1565.       tc_moves_remaining=tc_moves;
  1566.     }
  1567.     if (!tc_sudden_death) {
  1568.       Print(4095,"%d moves/%d minutes primary time control\n",
  1569.             tc_moves, tc_time/100);
  1570.       Print(4095,"%d moves/%d minutes secondary time control\n",
  1571.             tc_secondary_moves, tc_secondary_time/100);
  1572.       if (tc_increment) Print(4095,"increment %d seconds.\n",tc_increment/100);
  1573.     }
  1574.     else if (tc_sudden_death == 1) {
  1575.       Print(4095," game/%d minutes primary time control\n",tc_time/100);
  1576.       if (tc_increment) Print(4095,"increment %d seconds.\n",tc_increment/100);
  1577.     }
  1578.     tc_time*=60;
  1579.     tc_time_remaining=tc_time;
  1580.     tc_secondary_time*=60;
  1581.     if (tc_time > 30000 || tc_increment > 300) whisper=0;
  1582.     if (tc_time <= 6000 && tc_increment <= 100) whisper=0;
  1583.   }
  1584. /*
  1585.  ----------------------------------------------------------
  1586. |                                                          |
  1587. |   "list" command allows the operator to add or remove    |
  1588. |   names from the GM_list, IM_list , computer_list,       |
  1589. |   auto_kibitz_list or special_list.                      |
  1590. |   The  syntax is "list <list> <option> <name>.           |
  1591. |   <list> is one of GM, IM, C, AK or S.                   |
  1592. |   The final parameter is a name to add  or remove.       |
  1593. |   if the name is in the list, it is removed,             |
  1594. |   otherwise it is added.  if no name is given, the list  |
  1595. |   is displayed.                                          |
  1596. |                                                          |
  1597.  ----------------------------------------------------------
  1598. */
  1599.   else if (OptionMatch("list",*args)) {
  1600.     int i, j;
  1601.     char listname[8];
  1602.     char **targs;
  1603.  
  1604.     targs=args;
  1605.     strcpy(listname,args[1]);
  1606.     nargs-=2;
  1607.     targs+=2;
  1608.     
  1609.     if (nargs) {
  1610.       if (!strcmp(listname,"GM")) {
  1611.         if (targs[0][0] == '-') {
  1612.           for (i=0;i<number_of_GMs;i++)
  1613.             if (!strcmp(GM_list[i],targs[0]+1)) {
  1614.               for (j=i;j<number_of_GMs;j++)
  1615.                 strcpy(GM_list[j],GM_list[j+1]);
  1616.               number_of_GMs--;
  1617.               i=0;
  1618.               Print(4095,"%s removed from GM list.\n",targs[0]+1);
  1619.               break;
  1620.             }
  1621.         }
  1622.         else if (targs[0][0] == '+') {
  1623.           for (i=0;i<number_of_GMs;i++)
  1624.             if (!strcmp(GM_list[i],targs[0]+1)) {
  1625.               Print(4095, "Warning: %s is already in GM list.\n",targs[0]+1);
  1626.               break;
  1627.             }
  1628.           if (number_of_GMs >= 512)
  1629.             Print(4095,"ERROR!  GM list is full at 512 entries\n");
  1630.           else if (i==number_of_GMs) {
  1631.             strcpy(GM_list[number_of_GMs++],targs[0]+1);
  1632.             Print(4095,"%s added to GM list.\n",targs[0]+1);
  1633.           }
  1634.         }
  1635.         else if (!strcmp(targs[0],"clear")) {
  1636.           number_of_GMs=0;
  1637.         }
  1638.         else printf("error, name must be preceeded by +/- flag.\n");
  1639.       }
  1640.       if (!strcmp(listname,"S")) {
  1641.         if (targs[0][0] == '-') {
  1642.           for (i=0;i<number_of_specials;i++)
  1643.             if (!strcmp(special_list[i],targs[0]+1)) {
  1644.               for (j=i;j<number_of_specials;j++)
  1645.                 strcpy(special_list[j],special_list[j+1]);
  1646.               number_of_specials--;
  1647.               i=0;
  1648.               Print(4095,"%s removed from special list.\n",targs[0]+1);
  1649.  
  1650.               break;
  1651.             }
  1652.         }
  1653.         else if (targs[0][0] == '+') {
  1654.           for (i=0;i<number_of_specials;i++)
  1655.             if (!strcmp(special_list[i],targs[0]+1)) {
  1656.               Print(4095, "Warning: %s is already in S list.\n",targs[0]+1);
  1657.               break;
  1658.             }
  1659.           if (number_of_specials >= 512)
  1660.             Print(4095,"ERROR!  special list is full at 512 entries\n");
  1661.           else if (i==number_of_specials) {
  1662.             strcpy(special_list[number_of_specials++],targs[0]+1);
  1663.             Print(4095,"%s added to special list.\n",targs[0]+1);
  1664.           }
  1665.         }         
  1666.         else if (!strcmp(targs[0],"clear")) {
  1667.           number_of_specials=0;
  1668.         }
  1669.         else Print(4095,"error, name must be preceeded by +/- flag.\n");
  1670.       }
  1671.       if (!strcmp(listname,"IM")) {
  1672.         if (targs[0][0] == '-') {
  1673.           for (i=0;i<number_of_IMs;i++)
  1674.             if (!strcmp(IM_list[i],targs[0]+1)) {
  1675.               for (j=i;j<number_of_IMs;j++)
  1676.                 strcpy(IM_list[j],IM_list[j+1]);
  1677.               number_of_IMs--;
  1678.               i=0;
  1679.               Print(4095,"%s removed from IM list.\n",targs[0]+1);
  1680.  
  1681.               break;
  1682.             }
  1683.         }
  1684.         else if (targs[0][0] == '+') {
  1685.           for (i=0;i<number_of_IMs;i++)
  1686.             if (!strcmp(IM_list[i],targs[0]+1)) {
  1687.               Print(4095, "Warning: %s is already in IM list.\n",targs[0]+1);
  1688.               break;
  1689.             }
  1690.           if (number_of_IMs >= 512)
  1691.             Print(4095,"ERROR!  IM list is full at 512 entries\n");
  1692.           else if (i==number_of_IMs) {
  1693.             strcpy(IM_list[number_of_IMs++],targs[0]+1);
  1694.             Print(4095,"%s added to IM list.\n",targs[0]+1);
  1695.           }
  1696.         }         
  1697.         else if (!strcmp(targs[0],"clear")) {
  1698.           number_of_IMs=0;
  1699.         }
  1700.         else Print(4095,"error, name must be preceeded by +/- flag.\n");
  1701.       }
  1702.       if (!strcmp(listname,"C")) {
  1703.         if (targs[0][0] == '-') {
  1704.           for (i=0;i<number_of_computers;i++)
  1705.             if (!strcmp(computer_list[i],targs[0]+1)) {
  1706.               for (j=i;j<number_of_computers;j++)
  1707.                 strcpy(computer_list[j],computer_list[j+1]);
  1708.               number_of_computers--;
  1709.               i=0;
  1710.               Print(4095,"%s removed from computer list.\n",targs[0]+1);
  1711.               break;
  1712.             }
  1713.         }
  1714.         else if (targs[0][0] == '+') {
  1715.           for (i=0;i<number_of_computers;i++)
  1716.             if (!strcmp(computer_list[i],targs[0]+1)) {
  1717.               Print(4095, "Warning: %s is already in C list.\n",targs[0]+1);
  1718.               break;
  1719.             }
  1720.           if (number_of_computers >= 512)
  1721.             Print(4095,"ERROR!  C list is full at 512 entries\n");
  1722.           else if (i==number_of_computers) {
  1723.             strcpy(computer_list[number_of_computers++],targs[0]+1);
  1724.             Print(4095,"%s added to computer list.\n",targs[0]+1);
  1725.           }
  1726.         }
  1727.         else if (!strcmp(targs[0],"clear")) {
  1728.           number_of_computers=0;
  1729.         }
  1730.         else Print(4095,"error, name must be preceeded by +/- flag.\n");
  1731.       }
  1732.       
  1733.       if (!strcmp(listname,"AK")) {
  1734.         if (targs[0][0] == '-') {
  1735.           for (i=0;i<number_auto_kibitzers;i++)
  1736.             if (!strcmp(auto_kibitz_list[i],targs[0]+1)) {
  1737.               for (j=i;j<number_auto_kibitzers;j++)
  1738.                 strcpy(auto_kibitz_list[j],auto_kibitz_list[j+1]);
  1739.               number_auto_kibitzers--;
  1740.               i=0;
  1741.               Print(4095,"%s removed from auto kibitz list.\n",targs[0]+1);
  1742.               break;
  1743.             }
  1744.         }
  1745.         else if (targs[0][0] == '+') {
  1746.           for (i=0;i<number_auto_kibitzers;i++)
  1747.             if (!strcmp(auto_kibitz_list[i],targs[0]+1)) {
  1748.               Print(4095, "Warning: %s is already in AK list.\n",targs[0]+1);
  1749.               break;
  1750.             }
  1751.           if (number_auto_kibitzers >= 64)
  1752.             Print(4095,"ERROR!  AK list is full at 64 entries\n");
  1753.           else if (i==number_auto_kibitzers) {
  1754.             strcpy(auto_kibitz_list[number_auto_kibitzers++],targs[0]+1);
  1755.             Print(4095,"%s added to auto kibitz list.\n",targs[0]+1);
  1756.           }
  1757.         }
  1758.         else if (!strcmp(targs[0],"clear")) {
  1759.           number_auto_kibitzers=0;
  1760.         }
  1761.         else Print(4095,"error, name must be preceeded by +/- flag.\n");
  1762.       }
  1763.     }
  1764.     else {
  1765.       if (!strcmp(listname,"GM")) {
  1766.         Print(4095,"GM List:\n");
  1767.         for (i=0;i<number_of_GMs;i++)
  1768.           Print(4095,"%s\n",GM_list[i]);
  1769.       }
  1770.       else if (!strcmp(listname,"S")) {
  1771.         Print(4095,"special List:\n");
  1772.         for (i=0;i<number_of_specials;i++)
  1773.           Print(4095,"%s\n",special_list[i]);
  1774.       }
  1775.       else if (!strcmp(listname,"IM")) {
  1776.         Print(4095,"IM List:\n");
  1777.         for (i=0;i<number_of_IMs;i++)
  1778.           Print(4095,"%s\n",IM_list[i]);
  1779.       }
  1780.       else if (!strcmp(listname,"C")) {
  1781.         Print(4095, "computer list:\n");
  1782.         for (i=0;i<number_of_computers;i++)
  1783.           Print(4095,"%s\n",computer_list[i]);
  1784.       }
  1785.       else if (!strcmp(listname,"AK")) {
  1786.         Print(4095, "auto kibitz list:\n");
  1787.         for (i=0;i<number_auto_kibitzers;i++)
  1788.           Print(4095,"%s\n",auto_kibitz_list[i]);
  1789.       }
  1790.     }
  1791.   }
  1792. /*
  1793.  ----------------------------------------------------------
  1794. |                                                          |
  1795. |   "load" command directs the program to read input from  |
  1796. |   a file until a "setboard" command is found  this       |
  1797. |   command is then executed, setting up the position for  |
  1798. |   a search.                                              |
  1799. |                                                          |
  1800.  ----------------------------------------------------------
  1801. */
  1802.   else if (OptionMatch("load",*args)) {
  1803.     char title[64];
  1804.     char *readstat;
  1805.     FILE *prob_file;
  1806.  
  1807.     if (thinking || pondering) return(2);
  1808.     nargs=ReadParse(buffer,args,"     =");
  1809.     if (nargs < 3) {
  1810.       printf("usage:  input <filename> title\n");
  1811.       return(1);
  1812.     }
  1813.     if (!(prob_file=fopen(args[1],"r"))) {
  1814.       printf("file does not exist.\n");
  1815.       return(1);
  1816.     }
  1817.     strcpy(title,args[2]);
  1818.     while (!feof(prob_file)) {
  1819.       readstat=fgets(buffer,128,prob_file);
  1820.       if (readstat) {
  1821.         char *delim;
  1822.         delim=strchr(buffer,'\n');
  1823.         if (delim) *delim=0;
  1824.         delim=strchr(buffer,'\r');
  1825.         if (delim) *delim=' ';
  1826.       }
  1827.       if (readstat == NULL) break;
  1828.       nargs=ReadParse(buffer,args,"     ;\n");
  1829.       if (!strcmp(args[0],"title") && strstr(buffer,title)) break;
  1830.     }
  1831.     while (!feof(prob_file)) {
  1832.       readstat=fgets(buffer,128,prob_file);
  1833.       if (readstat) {
  1834.         char *delim;
  1835.         delim=strchr(buffer,'\n');
  1836.         if (delim) *delim=0;
  1837.         delim=strchr(buffer,'\r');
  1838.         if (delim) *delim=' ';
  1839.       }
  1840.       if (readstat == NULL) break;
  1841.       nargs=ReadParse(buffer,args,"     ;\n");
  1842.       if (!strcmp(args[0],"setboard")) {
  1843.         Option(tree);
  1844.         break;
  1845.       }
  1846.     }
  1847.   }
  1848. /*
  1849.  ----------------------------------------------------------
  1850. |                                                          |
  1851. |   "log" command turns log on/off, and also lets you view |
  1852. |   the end of the log or copy it to disk as needed.  To   |
  1853. |   view the end, simply type "log <n>" where n is the #   |
  1854. |   of lines you'd like to see (the last <n> lines).  you  |
  1855. |   can add a filename to the end and the output will go   |
  1856. |   to this file instead.                                  |
  1857. |                                                          |
  1858.  ----------------------------------------------------------
  1859. */
  1860.   else if (OptionMatch("log",*args)) {
  1861.     FILE *output_file;
  1862.     char filename[64], buffer[128];
  1863.  
  1864.     if (nargs < 2) {
  1865.       printf("usage:  log on|off|n [filename]\n");
  1866.       return(1);
  1867.     }
  1868.     if (!strcmp(args[1],"on")) {
  1869.       for (log_id=1;log_id <300;log_id++) {
  1870. #if defined(MACOS)
  1871.         sprintf(log_filename,":%s:log.%03d",log_path,log_id);
  1872.         sprintf(history_filename,":%s:game.%03d",log_path,log_id);
  1873. #else
  1874.         sprintf(log_filename,"%s/log.%03d",log_path,log_id);
  1875.         sprintf(history_filename,"%s/game.%03d",log_path,log_id);
  1876. #endif
  1877.         log_file=fopen(log_filename,"r");
  1878.         if (!log_file) break;
  1879.         fclose(log_file);
  1880.       }
  1881.       log_file=fopen(log_filename,"w");
  1882.       history_file=fopen(history_filename,"w+");
  1883.     }
  1884.     else if (!strcmp(args[1],"off")) {
  1885.       if (log_file) fclose(log_file);
  1886.       log_file=0;
  1887. #if defined(MACOS)
  1888.       sprintf(filename,":%s:log.%03d",log_path,log_id);
  1889. #else
  1890.       sprintf(filename,"%s/log.%03d",log_path,log_id);
  1891. #endif
  1892.       remove(filename);
  1893.     }
  1894.     else {
  1895.       int nrecs, trecs, lrecs;
  1896.       char *eof;
  1897.       FILE *log;
  1898.  
  1899.       nrecs=atoi(args[1]);
  1900.       output_file=stdout;
  1901.       if (nargs > 2) output_file=fopen(args[2],"w");
  1902.       log=fopen(log_filename,"r");
  1903.       for (trecs=1; trecs<99999999; trecs++) {
  1904.         eof=fgets(buffer,128,log);
  1905.         if (eof) {
  1906.           char *delim;
  1907.           delim=strchr(buffer,'\n');
  1908.           if (delim) *delim=0;
  1909.           delim=strchr(buffer,'\r');
  1910.           if (delim) *delim=' ';
  1911.         }
  1912.         else break;
  1913.       }
  1914.       fseek(log,0,SEEK_SET);
  1915.       for (lrecs=1; lrecs<trecs-nrecs; lrecs++) {
  1916.         eof=fgets(buffer,128,log);
  1917.         if (eof) {
  1918.           char *delim;
  1919.           delim=strchr(buffer,'\n');
  1920.           if (delim) *delim=0;
  1921.           delim=strchr(buffer,'\r');
  1922.           if (delim) *delim=' ';
  1923.         }
  1924.         else break;
  1925.       }
  1926.       for (;lrecs<trecs; lrecs++) {
  1927.         eof=fgets(buffer,128,log);
  1928.         if (eof) {
  1929.           char *delim;
  1930.           delim=strchr(buffer,'\n');
  1931.           if (delim) *delim=0;
  1932.           delim=strchr(buffer,'\r');
  1933.           if (delim) *delim=' ';
  1934.         }
  1935.         else break;
  1936.         fprintf(output_file,"%s\n",buffer);
  1937.       }
  1938.       if (output_file != stdout) fclose(output_file);
  1939.     }
  1940.   }
  1941. /*
  1942.  ----------------------------------------------------------
  1943. |                                                          |
  1944. |   "mt" command is used to set the maximum number of      |
  1945. |   parallel threads to use, assuming that Crafty was      |
  1946. |   compiled with -DSMP.  this value can not be set        |
  1947. |   larger than the compiled-in -DCPUS=n value.            |
  1948. |                                                          |
  1949.  ----------------------------------------------------------
  1950. */
  1951. #if defined(SMP)
  1952.   else if (OptionMatch("mt",*args)) {
  1953.     int proc;
  1954.     if (nargs < 2) {
  1955.       printf("usage:  mt=<threads>\n");
  1956.       return(1);
  1957.     }
  1958.     if (thinking || pondering) return(3);
  1959.     max_threads=atoi(args[1]);
  1960.     if (max_threads > CPUS) {
  1961.       Print(4095,"ERROR - Crafty was compiled with CPUS=%d.",CPUS);
  1962.       Print(4095,"  mt can not exceed this value.\n");
  1963.       max_threads=CPUS;
  1964.     }
  1965.     if (max_threads)
  1966.       Print(4095,"max threads set to %d\n",max_threads);
  1967.     else
  1968.       Print(4095,"parallel threads disabled.\n");
  1969.     for (proc=0;proc<CPUS;proc++)
  1970.       if (proc >= max_threads) thread[proc]=(TREE*)-1;
  1971.   }
  1972. /*
  1973.  ----------------------------------------------------------
  1974. |                                                          |
  1975. |   "mtmin" command is used to set the minimum depth of    |
  1976. |   a tree before a thread can be started.  this is used   |
  1977. |   to prevent the thread creation overhead from becoming  |
  1978. |   larger than the time actually needed to search the     |
  1979. |   tree.                                                  |
  1980. |                                                          |
  1981.  ----------------------------------------------------------
  1982. */
  1983.   else if (OptionMatch("mtmin",*args)) {
  1984.     if (nargs < 2) {
  1985.       printf("usage:  mtmin <plies>\n");
  1986.       return(1);
  1987.     }
  1988.     min_thread_depth=INCREMENT_PLY*atoi(args[1]);
  1989.     Print(4095,"minimum thread depth set to %d\n",min_thread_depth);
  1990.   }
  1991. #endif
  1992. /*
  1993.  ----------------------------------------------------------
  1994. |                                                          |
  1995. |   "mn" command is used to set the move number to a       |
  1996. |   specific value...                                      |
  1997. |                                                          |
  1998.  ----------------------------------------------------------
  1999. */
  2000.   else if (OptionMatch("mn",*args)) {
  2001.     if (nargs < 2) {
  2002.       printf("usage:  mn <move_number>\n");
  2003.       return(1);
  2004.     }
  2005.     move_number=atoi(args[1]);
  2006.     Print(4095,"move number set to %d\n",move_number);
  2007.   }
  2008. /*
  2009.  ----------------------------------------------------------
  2010. |                                                          |
  2011. |   "mode" command sets tournament mode or normal mode.    |
  2012. |   tournament mode is used when crafty is in a "real"     |
  2013. |   tournament.  it forces draw_score to 0, and makes      |
  2014. |   crafty display the chess clock after each move.        |
  2015. |                                                          |
  2016.  ----------------------------------------------------------
  2017. */
  2018.   else if (OptionMatch("mode",*args)) {
  2019.     if (nargs > 1) {
  2020.       if (!strcmp(args[1],"tournament")) {
  2021.         mode=tournament_mode;
  2022.         draw_score_normal=1;
  2023.         printf("use 'settc' command if a game is restarted after crafty\n");
  2024.         printf("has been terminated for any reason.\n");
  2025.       }
  2026.       else if (!strcmp(args[1],"normal")) {
  2027.         mode=normal_mode;
  2028.       }
  2029.       else {
  2030.         printf("usage:  mode normal|tournament\n");
  2031.         mode=normal_mode;
  2032.       }
  2033.     }
  2034.     if (mode == tournament_mode) printf("tournament mode.\n");
  2035.     else if (mode == normal_mode) printf("normal mode.\n");
  2036.   }
  2037. /*
  2038.  ----------------------------------------------------------
  2039. |                                                          |
  2040. |   "name" command saves opponents name and writes it into |
  2041. |   logfile along with the date/time.  it also scans the   |
  2042. |   list of known computers and adjusts its opening book   |
  2043. |   to play less "risky" if it matches.  if the opponent   |
  2044. |   is in the GM list, it tunes the resignation controls   |
  2045. |   to resign earlier.  ditto for IM, although the resign  |
  2046. |   threshold is not tightened so much.                    |
  2047. |                                                          |
  2048.  ----------------------------------------------------------
  2049. */
  2050.   else if (OptionMatch("name",*args)) {
  2051.     int i;
  2052.     char *next;
  2053.  
  2054.     if (nargs < 2) {
  2055.       printf("usage:  name <name>\n");
  2056.       return(1);
  2057.     }
  2058.     if (wtm) {
  2059.       strcpy(pgn_white,args[1]);
  2060.       sprintf(pgn_black,"Crafty %s",version);
  2061.     }
  2062.     else {
  2063.       strcpy(pgn_black,args[1]);
  2064.       sprintf(pgn_white,"Crafty %s",version);
  2065.     }
  2066.     Print(4095,"Crafty %s vs %s\n",version,args[1]);
  2067.     next=args[1];
  2068.     while (*next) {
  2069.       *next=tolower(*next);
  2070.       next++;
  2071.     }
  2072.     if (mode != tournament_mode) {
  2073.       for (i=0;i<number_auto_kibitzers;i++)
  2074.         if (!strcmp(auto_kibitz_list[i],args[1])) {
  2075.           kibitz=4;
  2076.           auto_kibitzing=1;
  2077.           break;
  2078.         }
  2079.       for (i=0;i<number_of_computers;i++)
  2080.         if (!strcmp(computer_list[i],args[1])) {
  2081.           Print(128,"playing a computer!\n");
  2082.           computer_opponent=1;
  2083.           draw_score_normal=1;
  2084.           book_selection_width=2;
  2085.           usage_level=0;
  2086.           book_weight_freq=1.0;
  2087.           book_weight_eval=.1;
  2088.           book_weight_learn=.2;
  2089.           break;
  2090.         }
  2091.       for (i=0;i<number_of_GMs;i++)
  2092.         if (!strcmp(GM_list[i],args[1])) {
  2093.           Print(128,"playing a GM!\n");
  2094.           book_selection_width=3;
  2095.           resign=Min(6,resign);
  2096.           resign_count=4;;
  2097.           draw_count=8;
  2098.           accept_draws=1;
  2099.           kibitz=0;
  2100.           break;
  2101.         }
  2102.       for (i=0;i<number_of_specials;i++)
  2103.         if (!strcmp(special_list[i],args[1])) {
  2104.           Print(128,"playing a special player!\n");
  2105.           book_selection_width=4;
  2106.           resign=Min(9,resign);
  2107.           resign_count=5;
  2108.           draw_count=8;
  2109.           kibitz=0;
  2110.           no_tricks=0;
  2111.           break;
  2112.         }
  2113.       for (i=0;i<number_of_IMs;i++)
  2114.         if (!strcmp(IM_list[i],args[1])) {
  2115.           Print(128,"playing an IM!\n");
  2116.           book_selection_width=4;
  2117.           resign=Min(9,resign);
  2118.           resign_count=5;
  2119.           draw_count=8;
  2120.           accept_draws=1;
  2121.           kibitz=0;
  2122.           break;
  2123.         }
  2124.       }
  2125.   }
  2126. /*
  2127.  ----------------------------------------------------------
  2128. |                                                          |
  2129. |   "new" command initializes for a new game.  note that   |
  2130. |   "AN" is an alias for this command, for auto232         |
  2131. |   compatibility.                                         |
  2132. |                                                          |
  2133.  ----------------------------------------------------------
  2134. */
  2135.   else if (OptionMatch("new",*args) || OptionMatch("AN",*args)) {
  2136.     new_game=1;
  2137.     if (thinking || pondering) return(3);
  2138.     NewGame(0);
  2139.     return(3);
  2140.   }
  2141. /*
  2142.  ----------------------------------------------------------
  2143. |                                                          |
  2144. |   "noise" command sets a minimum limit on nodes searched |
  2145. |   such that until this number of nodes has been searched |
  2146. |   no program output will occur.  this is used to prevent |
  2147. |   simple endgames from swamping the display device since |
  2148. |   30+ ply searches are possible, which can produce 100's |
  2149. |   of lines of output.                                    |
  2150. |                                                          |
  2151.  ----------------------------------------------------------
  2152. */
  2153.   else if (OptionMatch("noise",*args)) {
  2154.     if (nargs < 2) {
  2155.       printf("usage:  noise <n>\n");
  2156.       return(1);
  2157.     }
  2158.     noise_level=atoi(args[1]);
  2159.     Print(4095,"noise level set to %d.\n",noise_level);
  2160.   }
  2161. /*
  2162.  ----------------------------------------------------------
  2163. |                                                          |
  2164. |   "operator" command sets the operator time.  this time  |
  2165. |   is the time per move that the operator needs.  it is   |
  2166. |   multiplied by the number of moves left to time control |
  2167. |   to reserve operator time.                              |
  2168. |                                                          |
  2169.  ----------------------------------------------------------
  2170. */
  2171.   else if (OptionMatch("operator",*args)) {
  2172.     if (nargs < 2) {
  2173.       printf("usage:  operator <seconds>\n");
  2174.       return(1);
  2175.     }
  2176.     tc_operator_time=ParseTime(args[1])*100;
  2177.     Print(4095,"reserving %d seconds per move for operator overhead.\n",
  2178.           tc_operator_time/100);
  2179.   }
  2180. /*
  2181.  ----------------------------------------------------------
  2182. |                                                          |
  2183. |   "otime" command sets the opponent's time remaining.    |
  2184. |   this is used to determine if the opponent is in time   |
  2185. |   trouble, and is factored into the draw score if he is. |
  2186. |                                                          |
  2187.  ----------------------------------------------------------
  2188. */
  2189.   else if (OptionMatch("otime",*args)) {
  2190.     if (nargs < 2) {
  2191.       printf("usage:  otime <time(unit=.01 secs))>\n");
  2192.       return(1);
  2193.     }
  2194.     tc_time_remaining_opponent=atoi(args[1]);
  2195.     if (log_file && time_limit>99)
  2196.       fprintf(log_file,"time remaining: %s (opponent).\n",
  2197.               DisplayTime(tc_time_remaining_opponent));
  2198.     if (call_flag && xboard && tc_time_remaining_opponent <= 1) {
  2199.       if (crafty_is_white) Print(4095,"1-0 {Black ran out of time}\n");
  2200.       else Print(4095,"0-1 {White ran out of time}\n");
  2201.     }
  2202.   }
  2203. /*
  2204.  ----------------------------------------------------------
  2205. |                                                          |
  2206. |   "output" command sets long or short algebraic output.  |
  2207. |   long is Ng1f3, while short is simply Nf3.              |
  2208. |                                                          |
  2209.  ----------------------------------------------------------
  2210. */
  2211.   else if (OptionMatch("output",*args)) {
  2212.     if (nargs < 2) {
  2213.       printf("usage:  output long|short\n");
  2214.       return(1);
  2215.     }
  2216.     if (!strcmp(args[1],"long")) output_format=1;
  2217.     else if (!strcmp(args[1],"short")) output_format=0;
  2218.     else printf("usage:  output long|short\n");
  2219.     if (output_format == 1)
  2220.       Print(4095,"output moves in long algebraic format\n");
  2221.     else if (output_format == 0)
  2222.       Print(4095,"output moves in short algebraic format\n");
  2223.   }
  2224. /*
  2225.  ----------------------------------------------------------
  2226. |                                                          |
  2227. |   "bookpath", "logpath" and "tbpath" commands set the    |
  2228. |   default paths to find or create these files.           |
  2229. |                                                          |
  2230.  ----------------------------------------------------------
  2231. */
  2232.   else if (OptionMatch("logpath",*args) ||
  2233.            OptionMatch("bookpath",*args) ||
  2234.            OptionMatch("tbpath",*args)) {
  2235.     if (log_file)
  2236.       Print(4095,"ERROR -- this must be used on command line only\n");
  2237.     else {
  2238.       nargs=ReadParse(buffer,args,"     =");
  2239.       if (nargs < 2) {
  2240.         printf("usage:  bookpath|logpath|tbpath <path>\n");
  2241.         return(1);
  2242.       }
  2243.       if (strstr(args[0],"bookpath")) strcpy(book_path,args[1]);
  2244.       else if (strstr(args[0],"logpath")) strcpy(log_path,args[1]);
  2245.       else if (strstr(args[0],"tbpath")) strcpy(tb_path,args[1]);
  2246.     }
  2247.   }
  2248. /*
  2249.  ----------------------------------------------------------
  2250. |                                                          |
  2251. |   "perf" command turns times move generator/make_move.   |
  2252. |                                                          |
  2253.  ----------------------------------------------------------
  2254. */
  2255. #define PERF_CYCLES 100000
  2256.   else if (OptionMatch("perf",*args)) {
  2257.     int i, *mv, clock_before, clock_after;
  2258.     float time_used;
  2259.  
  2260.     if (thinking || pondering) return(2);
  2261.     clock_before = clock();
  2262.     while (clock() == clock_before);
  2263.     clock_before = clock();
  2264.     for (i=0;i<PERF_CYCLES;i++) {
  2265.       tree->last[1]=GenerateCaptures(tree, 0, wtm, tree->last[0]);
  2266.       tree->last[1]=GenerateNonCaptures(tree, 0, wtm, tree->last[1]);
  2267.     }
  2268.     clock_after=clock();
  2269.     time_used=((float) clock_after-(float) clock_before) / 
  2270.               (float) CLOCKS_PER_SEC;
  2271.     printf("generated %d moves, time=%.2f seconds\n",
  2272.            (tree->last[1]-tree->last[0])*PERF_CYCLES,time_used);
  2273.     printf("generated %d moves per second\n",(int) (((float) (PERF_CYCLES*
  2274.            (tree->last[1]-tree->last[0])))/time_used));
  2275.     clock_before=clock();
  2276.     while (clock() == clock_before);
  2277.     clock_before = clock();
  2278.     for (i=0;i<PERF_CYCLES;i++) {
  2279.       tree->last[1]=GenerateCaptures(tree, 0, wtm, tree->last[0]);
  2280.       tree->last[1]=GenerateNonCaptures(tree, 0, wtm, tree->last[1]);
  2281.       for (mv=tree->last[0];mv<tree->last[1];mv++) {
  2282.         MakeMove(tree,0,*mv,wtm);
  2283.         UnMakeMove(tree,0,*mv,wtm);
  2284.       }
  2285.     }
  2286.     clock_after=clock();
  2287.     time_used=((float) clock_after-(float) clock_before) / 
  2288.               (float) CLOCKS_PER_SEC;
  2289.     printf("generated/made/unmade %d moves, time=%.2f seconds\n",
  2290.       (tree->last[1]-tree->last[0])*PERF_CYCLES, time_used);
  2291.     printf("generated/made/unmade %d moves per second\n",(int) (((float) (PERF_CYCLES*
  2292.            (tree->last[1]-tree->last[0])))/time_used));
  2293.   }
  2294. /*
  2295.  ----------------------------------------------------------
  2296. |                                                          |
  2297. |   "perft" command turns tests move generator/make_move.  |
  2298. |                                                          |
  2299.  ----------------------------------------------------------
  2300. */
  2301.   else if (OptionMatch("perft",*args)) {
  2302.     int i;
  2303.  
  2304.     if (thinking || pondering) return(2);
  2305.     if (nargs < 2) {
  2306.       printf("usage:  perftest <depth>\n");
  2307.       return(1);
  2308.     }
  2309.     tree->position[1]=tree->position[0];
  2310.     tree->last[0]=tree->move_list;
  2311.     i=atoi(args[1]);
  2312.     total_moves=0;
  2313.     OptionPerft(tree,1,i,wtm);
  2314.     printf("total moves=%d\n",total_moves);
  2315.   }
  2316. /*
  2317.  ----------------------------------------------------------
  2318. |                                                          |
  2319. |   "pgn" command sets the various PGN header files.       |
  2320. |                                                          |
  2321.  ----------------------------------------------------------
  2322. */
  2323.   else if (OptionMatch("pgn",*args)) {
  2324.     int i;
  2325.  
  2326.     if (nargs < 3) {
  2327.       printf("usage:  pgn <tag> <value>\n");
  2328.       return(1);
  2329.     }
  2330.     if (!strcmp(args[1],"Event")) {
  2331.       pgn_event[0]=0;
  2332.       for (i=2;i<nargs;i++) {
  2333.         strcpy(pgn_event+strlen(pgn_event),args[i]);
  2334.         strcpy(pgn_event+strlen(pgn_event)," ");
  2335.       }
  2336.     }
  2337.     else if (!strcmp(args[1],"Site")) {
  2338.       pgn_site[0]=0;
  2339.       for (i=2;i<nargs;i++) {
  2340.         strcpy(pgn_site+strlen(pgn_site),args[i]);
  2341.         strcpy(pgn_site+strlen(pgn_site)," ");
  2342.       }
  2343.     }
  2344.     else if (!strcmp(args[1],"Round")) {
  2345.       pgn_round[0]=0;
  2346.       strcpy(pgn_round,args[2]);
  2347.     }
  2348.     else if (!strcmp(args[1],"White")) {
  2349.       pgn_white[0]=0;
  2350.       for (i=2;i<nargs;i++) {
  2351.         strcpy(pgn_white+strlen(pgn_white),args[i]);
  2352.         strcpy(pgn_white+strlen(pgn_white)," ");
  2353.       }
  2354.     }
  2355.     else if (!strcmp(args[1],"WhiteElo")) {
  2356.       pgn_white_elo[0]=0;
  2357.       strcpy(pgn_white_elo,args[2]);
  2358.     }
  2359.     else if (!strcmp(args[1],"Black")) {
  2360.       pgn_black[0]=0;
  2361.       for (i=2;i<nargs;i++) {
  2362.         strcpy(pgn_black+strlen(pgn_black),args[i]);
  2363.         strcpy(pgn_black+strlen(pgn_black)," ");
  2364.       }
  2365.     }
  2366.     else if (!strcmp(args[1],"BlackElo")) {
  2367.       pgn_black_elo[0]=0;
  2368.       strcpy(pgn_black_elo,args[2]);
  2369.     }
  2370.   }
  2371. /*
  2372.  ----------------------------------------------------------
  2373. |                                                          |
  2374. |   "ponder" command toggles pondering off/on or sets a    |
  2375. |   move to ponder.                                        |
  2376. |                                                          |
  2377.  ----------------------------------------------------------
  2378. */
  2379.   else if (OptionMatch("ponder",*args)) {
  2380.     if (thinking || pondering) return(2);
  2381.     if (nargs < 2) {
  2382.       printf("usage:  ponder off|on|<move>\n");
  2383.       return(1);
  2384.     }
  2385.     if (!strcmp(args[1],"on")) {
  2386.       ponder=1;
  2387.       Print(4095,"pondering enabled.\n");
  2388.     }
  2389.     else if (!strcmp(args[1],"off")) {
  2390.       ponder=0;
  2391.       Print(4095,"pondering disabled.\n");
  2392.     }
  2393.     else {
  2394.       ponder_move=InputMove(tree,args[1],0,wtm,0,0);
  2395.     }
  2396.   }
  2397. /*
  2398.  ----------------------------------------------------------
  2399. |                                                          |
  2400. |   "post/nopost" command sets/resets "show thinking" mode |
  2401. |   for xboard compatibility.                              |
  2402. |                                                          |
  2403.  ----------------------------------------------------------
  2404. */
  2405.   else if (!strcmp("post",*args)) {
  2406.     post=1;
  2407.   }
  2408.   else if (!strcmp("nopost",*args)) {
  2409.     post=0;
  2410.   }
  2411. /*
  2412.  ----------------------------------------------------------
  2413. |                                                          |
  2414. |  "random" command is ignored. [xboard compatibility]     |
  2415. |                                                          |
  2416.  ----------------------------------------------------------
  2417. */
  2418.   else if (OptionMatch("random",*args)) {
  2419.     return(xboard);
  2420.   }
  2421. /*
  2422.  ----------------------------------------------------------
  2423. |                                                          |
  2424. |   "rating" is used by xboard to set crafty's rating and  |
  2425. |   the opponent's rating, which is used by the learning   |
  2426. |   functions.                                             |
  2427. |                                                          |
  2428.  ----------------------------------------------------------
  2429. */
  2430.   else if (OptionMatch("rating",*args)) {
  2431.     if (nargs < 3) {
  2432.       printf("usage:  rating <crafty> <opponent>\n");
  2433.       return(1);
  2434.     }
  2435.     crafty_rating=atoi(args[1]);
  2436.     opponent_rating=atoi(args[2]);
  2437.     if (opponent_rating-crafty_rating > 0) default_draw_score=20;
  2438.     if (log_file) {
  2439.       fprintf(log_file,"Crafty's rating: %d.\n",crafty_rating);
  2440.       fprintf(log_file,"opponent's rating: %d.\n",opponent_rating);
  2441.     }
  2442.   }
  2443. /*
  2444.  ----------------------------------------------------------
  2445. |                                                          |
  2446. |   "remove" command backs up the game one whole move,     |
  2447. |   leaving the opponent still on move.  it's intended for |
  2448. |   xboard compatibility, but works in any mode.           |
  2449. |                                                          |
  2450.  ----------------------------------------------------------
  2451. */
  2452.   else if (!strcmp("remove",*args)) {
  2453.     if (thinking || pondering) return(2);
  2454.     move_number--;
  2455.     sprintf(buffer,"reset %d",move_number);
  2456.     (void) Option(tree);
  2457.   }
  2458. /*
  2459.  ----------------------------------------------------------
  2460. |                                                          |
  2461. |   "reset" restores (backs up) a game to a prior position |
  2462. |   with the same side on move.  reset 17 would reset the  |
  2463. |   position to what it was at move 17.                    |
  2464. |                                                          |
  2465.  ----------------------------------------------------------
  2466. */
  2467.   else if (OptionMatch("reset",*args)) {
  2468.     int i, move, nmoves;
  2469.  
  2470.     if (thinking || pondering) return(2);
  2471.     if (nargs < 2) {
  2472.       printf("usage:  reset <movenumber>\n");
  2473.       return(1);
  2474.     }
  2475.     ponder_move=0;
  2476.     last_mate_score=0;
  2477.     last_pv.path_iteration_depth=0;
  2478.     last_pv.path_length=0;
  2479.     if (thinking || pondering) return(2);
  2480.     over=0;
  2481.     move_number=atoi(args[1]);
  2482.     if (!move_number) {
  2483.       move_number=1;
  2484.       return(1);
  2485.     }
  2486.     nmoves=(move_number-1)*2+1-wtm;
  2487.     root_wtm=ChangeSide(wtm);
  2488.     InitializeChessBoard(&tree->position[0]);
  2489.     wtm=1;
  2490.     move_number=1;
  2491.     for (i=0;i<nmoves;i++) {
  2492.       fseek(history_file,i*10,SEEK_SET);
  2493.       fscanf(history_file,"%s",buffer);
  2494. /*
  2495.     If the move is "pass", that means that the side on move passed.
  2496.     This includes the case where the game started from a black-to-move
  2497.     position; then white's first move is recorded as a pass.
  2498. */
  2499.       if(strcmp(buffer,"pass")==0) {
  2500.     wtm=ChangeSide(wtm);
  2501.     if (wtm) move_number++;
  2502.     continue;
  2503.       }
  2504.       move=InputMove(tree,buffer,0,wtm,0,0);
  2505.       if (move) {
  2506.         MakeMoveRoot(tree,move,wtm);
  2507.       }
  2508.       else {
  2509.         printf("ERROR!  move %s is illegal\n",buffer);
  2510.         break;
  2511.       }
  2512.       wtm=ChangeSide(wtm);
  2513.       if (wtm) move_number++;
  2514.       Phase();
  2515.     } 
  2516.     moves_out_of_book=0;
  2517.     tc_moves_remaining=tc_moves-move_number+1;
  2518.     while (tc_moves_remaining <= 0) tc_moves_remaining+=tc_secondary_moves;
  2519.     printf("NOTICE: %d moves to next time control\n",tc_moves_remaining);
  2520.   }
  2521. /*
  2522.  ----------------------------------------------------------
  2523. |                                                          |
  2524. |   "read" reads game moves in and makes them.  this can   |
  2525. |   be used in two ways:  (1) type "read" and then start   |
  2526. |   entering moves;  type "exit" when done;  (2) type      |
  2527. |   "read <filename>" to read moves in from <filename>.    |
  2528. |   note that read will attempt to skip over "non-move"    |
  2529. |   text and try to extract moves if it can.               |
  2530. |                                                          |
  2531.  ----------------------------------------------------------
  2532. */
  2533.   else if (OptionMatch("read",*args) || OptionMatch("reada",*args)) {
  2534.     int append, move, readstat;
  2535.     FILE *read_input=0;
  2536.  
  2537.     if (thinking || pondering) return(2);
  2538.     nargs=ReadParse(buffer,args,"     =");
  2539.     if (!strcmp("reada",*args))
  2540.       append=1;
  2541.     else
  2542.       append=0;
  2543.     ponder_move=0;
  2544.     last_pv.path_iteration_depth=0;
  2545.     last_pv.path_length=0;
  2546.     if (nargs > 1) {
  2547.       if (!(read_input=fopen(args[1],"r"))) {
  2548.         printf("file %s does not exist.\n",args[1]);
  2549.         return(1);
  2550.       }
  2551.     }
  2552.     else {
  2553.       printf("type \"exit\" to terminate.\n");
  2554.       read_input=stdin;
  2555.     }
  2556.     if (!append) {
  2557.       InitializeChessBoard(&tree->position[0]);
  2558.       wtm=1;
  2559.       move_number=1;
  2560.     }
  2561. /*
  2562.    step 1:  read in the PGN tags.
  2563. */
  2564.     readstat=ReadPGN(0,0);
  2565.     do {
  2566.       if (read_input == stdin) {
  2567.         if (wtm)
  2568.           printf("read.White(%d): ",move_number);
  2569.         else
  2570.           printf("read.Black(%d): ",move_number);
  2571.         fflush(stdout);
  2572.       }
  2573.       readstat=ReadPGN(read_input,0);
  2574.     } while (readstat==1);
  2575.     if (readstat < 0) return(1);
  2576. /*
  2577.    step 2:  read in the moves.
  2578. */
  2579.     do {
  2580.       move=0;
  2581.       move=ReadNextMove(tree,buffer,0,wtm);
  2582.       if (move) {
  2583.         if (read_input != stdin) {
  2584.           printf("%s ",OutputMove(tree,move,0,wtm));
  2585.           if (!(move_number % 8) && ChangeSide(wtm)) printf("\n");
  2586.         }
  2587.         fseek(history_file,((move_number-1)*2+1-wtm)*10,SEEK_SET);
  2588.         fprintf(history_file,"%9s\n",OutputMove(tree,move,0,wtm));
  2589.         MakeMoveRoot(tree,move,wtm);
  2590. #if defined(DEBUG)
  2591.         ValidatePosition(tree,1,move,"Option()");
  2592. #endif
  2593.       }
  2594.       else if (!read_input) printf("illegal move.\n");
  2595.       if (move) {
  2596.         wtm=ChangeSide(wtm);
  2597.         Phase();
  2598.         if (wtm) move_number++;
  2599.       }
  2600.       if (read_input == stdin) {
  2601.         if (wtm)
  2602.           printf("read.White(%d): ",move_number);
  2603.         else
  2604.           printf("read.Black(%d): ",move_number);
  2605.         fflush(stdout);
  2606.       }
  2607.       readstat=ReadPGN(read_input,0);
  2608.       if (readstat < 0) break;
  2609.       if (!strcmp(buffer,"exit")) break;
  2610.     } while (1);
  2611.     moves_out_of_book=0;
  2612.     if (read_input != stdin) {
  2613.       printf("\n");
  2614.       fclose(read_input);
  2615.     }
  2616.   }
  2617. /*
  2618.  ----------------------------------------------------------
  2619. |                                                          |
  2620. |   "resign" command sets the resignation threshold to     |
  2621. |   the number of pawns the program must be behind before  |
  2622. |   resigning (0 -> disable resignations).  resign with no |
  2623. |   arguments will mark the pgn result as lost by the      |
  2624. |   opponent.                                              |
  2625. |                                                          |
  2626.  ----------------------------------------------------------
  2627. */
  2628.   else if (OptionMatch("resign",*args)) {
  2629.     if (nargs < 2) {
  2630.       if (crafty_is_white) {
  2631.         Print(4095,"result 1-0\n");
  2632.         strcpy(pgn_result,"1-0");
  2633.       }
  2634.       else {
  2635.         Print(4095,"result 0-1\n");
  2636.         strcpy(pgn_result,"0-1");
  2637.       }
  2638.       return(1);
  2639.     }
  2640.     resign=atoi(args[1]);
  2641.     if (resign)
  2642.       Print(128,"threshold set to %d pawns.\n",resign);
  2643.     else
  2644.       Print(128,"disabled resignations.\n");
  2645.   }
  2646. /*
  2647.  ----------------------------------------------------------
  2648. |                                                          |
  2649. |   "result" command comes from xboard/winboard and gives  |
  2650. |   the result of the current game.  if learning routines  |
  2651. |   have not yet been activated, this will do it.          |
  2652. |                                                          |
  2653.  ----------------------------------------------------------
  2654. */
  2655.   else if (OptionMatch("result",*args)) {
  2656.     if (nargs > 1) {
  2657.       if (!strcmp(args[1],"1-0")) {
  2658.         strcpy(pgn_result,"1-0");
  2659.         if (!crafty_is_white) LearnResult(tree,crafty_is_white);
  2660.       }
  2661.       else if (!strcmp(args[1],"0-1")) {
  2662.         strcpy(pgn_result,"0-1");
  2663.         if (crafty_is_white) LearnResult(tree,crafty_is_white);
  2664.       }
  2665.       else if (!strcmp(args[1],"1/2-1/2")) {
  2666.         strcpy(pgn_result,"1/2-1/2");
  2667.       }
  2668.       return(1);
  2669.     }
  2670.   }
  2671. /*
  2672.  ----------------------------------------------------------
  2673. |                                                          |
  2674. |   "savegame" command saves the game in a file in PGN     |
  2675. |   format.  command has an optional filename.  note that  |
  2676. |   SR is an auto232alias that behaves slightly            |
  2677. |   differently.                                           |
  2678. |                                                          |
  2679.  ----------------------------------------------------------
  2680. */
  2681.   else if (OptionMatch("savegame",*args) ||
  2682.            OptionMatch("SR",*args)) {
  2683.     struct tm *timestruct;
  2684.     int i, secs, more, swtm;
  2685.     FILE *output_file;
  2686.     char input[128], text[128], *next, *tomove;
  2687.  
  2688.     output_file=stdout;
  2689.     secs=time(0);
  2690.     timestruct=localtime((time_t*) &secs);
  2691.     if (nargs > 1) {
  2692.       if (!(output_file=fopen(args[1],"w"))) {
  2693.         printf("unable to open %s for write.\n",args[1]);
  2694.         return(1);
  2695.       }
  2696.     }
  2697.     fprintf(output_file,"[Event \"%s\"]\n",pgn_event);
  2698.     fprintf(output_file,"[Site \"%s\"]\n",pgn_site);
  2699.     fprintf(output_file,"[Date \"%4d.%02d.%02d\"]\n",timestruct->tm_year+1900,
  2700.             timestruct->tm_mon+1,timestruct->tm_mday);
  2701.     fprintf(output_file,"[Round \"%s\"]\n",pgn_round);
  2702.     fprintf(output_file,"[White \"%s\"]\n",pgn_white);
  2703.     fprintf(output_file,"[WhiteElo \"%s\"]\n",pgn_white_elo);
  2704.     fprintf(output_file,"[Black \"%s\"]\n",pgn_black);
  2705.     fprintf(output_file,"[BlackElo \"%s\"]\n",pgn_black_elo);
  2706.     fprintf(output_file,"[Result \"%s\"]\n",pgn_result);
  2707.     /* Handle setup positions and initial pass by white */
  2708.     swtm=1;
  2709.     if (move_number>1 || !wtm) {
  2710.       fseek(history_file,0,SEEK_SET);
  2711.       if (fscanf(history_file,"%s",input)==1 && strcmp(input,"pass")==0) {
  2712.     swtm=0;
  2713.       }
  2714.     }
  2715.     if (initial_position[0]) {
  2716.       tomove=strchr(initial_position,' ');
  2717.       tomove[1]=(swtm?'w':'b');
  2718.       fprintf(output_file,"[FEN \"%s\"]\n[SetUp \"1\"]\n",initial_position);
  2719.     } else if (!swtm) {
  2720.       fprintf(output_file,
  2721.         "[FEN \"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR b KQkq - 0 1\"\n"
  2722.     "[SetUp \"1\"]\n");
  2723.     }
  2724.     fprintf(output_file,"\n");
  2725.     next=text;
  2726.     if (!swtm) {
  2727.       strcpy(next,"1... ");
  2728.       next=text+strlen(text);
  2729.     }
  2730. /* Output the moves */
  2731.     more=0;
  2732.     for (i=(swtm?0:1);i<(move_number-1)*2-wtm+1;i++) {
  2733.       fseek(history_file,i*10,SEEK_SET);
  2734.       fscanf(history_file,"%s",input);
  2735.       if (!(i%2)) {
  2736.         sprintf(next,"%d. ",i/2+1);
  2737.         next=text+strlen(text);
  2738.       }
  2739.       sprintf(next,"%s ",input);
  2740.       next=text+strlen(text);
  2741.       more=1;
  2742.       if (next-text >= 60) {
  2743.         fprintf(output_file,"%s\n",text);
  2744.         more=0;
  2745.         next=text;
  2746.       }
  2747.     }
  2748.     if (more)
  2749.       fprintf(output_file,"%s",text);
  2750.     fprintf(output_file,"%s\n",pgn_result);
  2751.     if (output_file != stdout) fclose(output_file);
  2752.     printf("PGN save complete.\n");
  2753.   }
  2754. /*
  2755.  ----------------------------------------------------------
  2756. |                                                          |
  2757. |   "savepos" command saves the current position in a FEN  |
  2758. |   (Forsythe notation) string that can be later used to   |
  2759. |   recreate this exact position.                          |
  2760. |                                                          |
  2761.  ----------------------------------------------------------
  2762. */
  2763.   else if (OptionMatch("savepos",*args)) {
  2764.     char xlate[15]={'q','r','b',0,'k','n','p',0,'P','N','K',0,'B','R','Q'};
  2765.     char empty[9]={' ','1','2','3','4','5','6','7','8'};
  2766.     int rank, file, nempty;
  2767.     FILE *output_file;
  2768.   
  2769.     output_file=stdout;
  2770.     if (nargs > 1) {
  2771.       if (!strcmp(args[1],"*")) {
  2772.         output_file=0;
  2773.         strcpy(initial_position,"");
  2774.       }
  2775.       else if (!(output_file=fopen(args[1],"w"))) {
  2776.         printf("unable to open %s for write.\n",args[1]);
  2777.         return(1);
  2778.       }
  2779.     }
  2780.     if (output_file) fprintf(output_file,"setboard ");
  2781.     for (rank=RANK8;rank>=RANK1;rank--) {
  2782.       nempty=0;
  2783.       for (file=FILEA;file<=FILEH;file++) {
  2784.         if (PieceOnSquare((rank<<3)+file)) {
  2785.           if (nempty) {
  2786.             if (output_file)
  2787.               fprintf(output_file,"%c",empty[nempty]);
  2788.             else
  2789.               sprintf(initial_position+strlen(initial_position),"%c",
  2790.                       empty[nempty]);
  2791.             nempty=0;
  2792.           }
  2793.           if (output_file)
  2794.             fprintf(output_file,"%c",xlate[PieceOnSquare((rank<<3)+file)+7]);
  2795.             else
  2796.               sprintf(initial_position+strlen(initial_position),"%c",
  2797.                       xlate[PieceOnSquare((rank<<3)+file)+7]);
  2798.         }
  2799.         else nempty++;
  2800.       }
  2801.       if (output_file)
  2802.         fprintf(output_file,"/");
  2803.       else
  2804.         sprintf(initial_position+strlen(initial_position),"%c",'/');
  2805.     }
  2806.     if (output_file)
  2807.       fprintf(output_file," %c ",(wtm)?'w':'b');
  2808.     else
  2809.       sprintf(initial_position+strlen(initial_position)," %c ", (wtm)?'w':'b');
  2810.     if (WhiteCastle(0) & 1) {
  2811.       if (output_file)
  2812.         fprintf(output_file,"K");
  2813.       else
  2814.         sprintf(initial_position+strlen(initial_position),"%c",'K');
  2815.     }
  2816.     if (WhiteCastle(0) & 2) {
  2817.       if (output_file)
  2818.         fprintf(output_file,"Q");
  2819.       else
  2820.         sprintf(initial_position+strlen(initial_position),"%c",'Q');
  2821.     }
  2822.     if (BlackCastle(0) & 1) {
  2823.       if (output_file)
  2824.         fprintf(output_file,"k");
  2825.       else
  2826.         sprintf(initial_position+strlen(initial_position),"%c",'k');
  2827.     }
  2828.     if (BlackCastle(0) & 2) {
  2829.       if (output_file)
  2830.         fprintf(output_file,"q");
  2831.       else
  2832.         sprintf(initial_position+strlen(initial_position),"%c",'q');
  2833.     }
  2834.     if (EnPassant(0)) {
  2835.       if (output_file)
  2836.         fprintf(output_file," %c%c",File(EnPassant(0))+'a',
  2837.                               Rank(EnPassant(0))+'1');
  2838.       else
  2839.         sprintf(initial_position+strlen(initial_position), "%c%c",
  2840.                 File(EnPassant(0))+'a',
  2841.                 Rank(EnPassant(0))+'1');
  2842.     }
  2843.     if (output_file) fprintf(output_file,"\n");
  2844.  
  2845.     if (output_file && output_file != stdout) {
  2846.       fprintf(output_file,"exit\n");
  2847.       fclose(output_file);
  2848.     }
  2849.     if (output_file) printf("FEN save complete.\n");
  2850.   }
  2851. /*
  2852.  ----------------------------------------------------------
  2853. |                                                          |
  2854. |   "search" command sets a specific move for the search   |
  2855. |   to analyze, ignoring all others completely.            |
  2856. |                                                          |
  2857.  ----------------------------------------------------------
  2858. */
  2859.   else if (OptionMatch("search",*args)) {
  2860.     if (thinking || pondering) return(2);
  2861.     if (nargs < 2) {
  2862.       printf("usage:  search <move>\n");
  2863.       return(1);
  2864.     }
  2865.     search_move=InputMove(tree,args[1],0,wtm,0,0);
  2866.     if (!search_move) search_move=InputMove(tree,args[1],0,ChangeSide(wtm),0,0);
  2867.     if (!search_move) printf("illegal move.\n");
  2868.   }
  2869. /*
  2870.  ----------------------------------------------------------
  2871. |                                                          |
  2872. |   "settc" command is used to reset the time controls     |
  2873. |   after a complete restart.                              |
  2874. |                                                          |
  2875.  ----------------------------------------------------------
  2876. */
  2877.   else if (OptionMatch("settc",*args)) {
  2878.     if (thinking || pondering) return(2);
  2879.     if (nargs < 4) {
  2880.       printf("usage:  settc <moves> <ctime> <otime>\n");
  2881.       return(1);
  2882.     }
  2883.     tc_moves_remaining=atoi(args[1]);
  2884.     tc_time_remaining=ParseTime(args[2])*6000;
  2885.     tc_time_remaining_opponent=ParseTime(args[3])*6000;
  2886.     Print(4095,"time remaining: %s (crafty).\n",
  2887.             DisplayTime(tc_time_remaining));
  2888.     Print(4095,"time remaining: %s (opponent).\n",
  2889.             DisplayTime(tc_time_remaining_opponent));
  2890.     Print(4095,"%d moves to next time control (Crafty)\n",
  2891.           tc_moves_remaining);
  2892.   }
  2893. /*
  2894.  ----------------------------------------------------------
  2895. |                                                          |
  2896. |   "setboard" command sets the board to a specific        |
  2897. |   position for analysis by the program.                  |
  2898. |                                                          |
  2899.  ----------------------------------------------------------
  2900. */
  2901.   else if (OptionMatch("setboard",*args)) {
  2902.     if (thinking || pondering) return(2);
  2903.     nargs=ReadParse(buffer,args,"     ;=");
  2904.     SetBoard(nargs-1,args+1,0);
  2905.     move_number=1;
  2906.     if (!wtm) {
  2907.       wtm=1;
  2908.       Pass();
  2909.     }
  2910.     ponder_move=0;
  2911.     last_pv.path_iteration_depth=0;
  2912.     last_pv.path_length=0;
  2913.     over=0;
  2914.     strcpy(buffer,"savepos *");
  2915.     (void) Option(tree);
  2916.   }
  2917. /*
  2918.  ----------------------------------------------------------
  2919. |                                                          |
  2920. |   "score" command displays static evaluation of the      |
  2921. |   current board position.                                |
  2922. |                                                          |
  2923.  ----------------------------------------------------------
  2924. */
  2925.   else if (OptionMatch("score",*args)) {
  2926.     int s1, s2=0, s3=0, s4=0, s5=0, s6;
  2927.  
  2928.     if (thinking || pondering) return(2);
  2929.     root_wtm=ChangeSide(wtm);
  2930.     tree->position[1]=tree->position[0];
  2931.     PreEvaluate(tree,wtm);
  2932.     s6=Evaluate(tree,1,1,-99999,99999);
  2933.     s1=Material;
  2934.     if (opening) s2=EvaluateDevelopment(tree,1);
  2935.     if (TotalWhitePawns+TotalBlackPawns) {
  2936.       tree->all_pawns=Or(WhitePawns,BlackPawns);
  2937.       s3=EvaluatePawns(tree);
  2938.       s4=EvaluatePassedPawns(tree);
  2939.       s5=EvaluatePassedPawnRaces(tree,wtm);
  2940.     }
  2941.     Print(128,"note: scores are for the white side\n");
  2942.     Print(128,"material evaluation.................%s\n",
  2943.       DisplayEvaluation(s1));
  2944.     Print(128,"development.........................%s\n",
  2945.       DisplayEvaluation(s2));
  2946.     Print(128,"pawn evaluation.....................%s\n",
  2947.       DisplayEvaluation(s3));
  2948.     Print(128,"passed pawn evaluation..............%s\n",
  2949.       DisplayEvaluation(s4));
  2950.     Print(128,"passed pawn race evaluation.........%s\n",
  2951.       DisplayEvaluation(s5));
  2952.     Print(128,"interactive piece evaluation........%s\n",
  2953.       DisplayEvaluation(s6-s1-s2-s3-s4-s5));
  2954.     Print(128,"total evaluation....................%s\n",
  2955.       DisplayEvaluation(s6));
  2956.   }
  2957. /*
  2958.  ----------------------------------------------------------
  2959. |                                                          |
  2960. |   "sd" command sets a specific search depth to control   |
  2961. |   the tree search depth.                                 |
  2962. |                                                          |
  2963.  ----------------------------------------------------------
  2964. */
  2965.   else if (OptionMatch("sd",*args)) {
  2966.     if (nargs < 2) {
  2967.       printf("usage:  sd <depth>\n");
  2968.       return(1);
  2969.     }
  2970.     search_depth=atoi(args[1]);
  2971.     Print(4095,"search depth set to %d.\n",search_depth);
  2972.   }
  2973. /*
  2974.  ----------------------------------------------------------
  2975. |                                                          |
  2976. |   "show" command enables/disables various display        |
  2977. |   such as "show extensions" which adds a character to    |
  2978. |   each pv move showing if/why it was extended.           |
  2979. |                                                          |
  2980.  ----------------------------------------------------------
  2981. */
  2982.   else if (OptionMatch("show",*args)) {
  2983.     if (nargs < 2) {
  2984.       printf("usage:  show book\n");
  2985.       return(1);
  2986.     }
  2987.     if (OptionMatch("book",args[1])) {
  2988.       show_book=!show_book;
  2989.       if (show_book) Print(4095,"show book statistics\n");
  2990.       else Print(4095,"don't show book statistics\n");
  2991.     }
  2992.   }
  2993. /*
  2994.  ----------------------------------------------------------
  2995. |                                                          |
  2996. |   "SP" command does nothing, except force main() to      |
  2997. |   start a search.  [auto232 compatibility]               |
  2998. |                                                          |
  2999.  ----------------------------------------------------------
  3000. */
  3001.   else if (OptionMatch("SP",*args)) {
  3002.     if (thinking) return(2);
  3003.     return(-1);
  3004.   }
  3005. /*
  3006.  ----------------------------------------------------------
  3007. |                                                          |
  3008. |   "st" command sets a specific search time to control    |
  3009. |   the tree search time.                                  |
  3010. |                                                          |
  3011.  ----------------------------------------------------------
  3012. */
  3013.   else if (OptionMatch("st",*args)) {
  3014.     int fract;
  3015.     if (nargs < 2) {
  3016.       printf("usage:  st <time>\n");
  3017.       return(1);
  3018.     }
  3019.     search_time_limit=atoi(args[1])*100;
  3020.     if (strchr(args[1],'.')) {
  3021.       fract=atoi(strchr(args[1],'.')+1);
  3022.       if (fract<10 && *(strchr(args[1],'.')+1) != '0') fract*=10;
  3023.       search_time_limit+=fract;
  3024.     }
  3025.     Print(4095,"search time set to %.2f.\n",(float)search_time_limit/100.0);
  3026.   }
  3027. /*
  3028.  ----------------------------------------------------------
  3029. |                                                          |
  3030. |   "surplus" command sets a specific time surplus target  |
  3031. |   for normal tournament games.                           |
  3032. |                                                          |
  3033.  ----------------------------------------------------------
  3034. */
  3035.   else if (OptionMatch("surplus",*args)) {
  3036.     if (nargs == 2) tc_safety_margin=atoi(args[1])*6000;
  3037.     Print(4095,"time surplus set to %s.\n",DisplayTime(tc_safety_margin));
  3038.   }
  3039. /*
  3040.  ----------------------------------------------------------
  3041. |                                                          |
  3042. |   "test" command runs a test suite of problems and       |
  3043. |   prints results.                                        |
  3044. |                                                          |
  3045.  ----------------------------------------------------------
  3046. */
  3047.   else if (OptionMatch("test",*args)) {
  3048.     nargs=ReadParse(buffer,args,"     ;=");
  3049.     if (thinking || pondering) return(2);
  3050.     if (nargs < 2) {
  3051.       printf("usage:  test <filename> [exitcnt]\n");
  3052.       return(1);
  3053.     }
  3054.     if (nargs > 2) early_exit=atoi(args[2]);
  3055.     Test(args[1]);
  3056.     ponder_move=0;
  3057.     last_pv.path_iteration_depth=0;
  3058.     last_pv.path_length=0;
  3059.   }
  3060. /*
  3061.  ----------------------------------------------------------
  3062. |                                                          |
  3063. |   "time" controls whether the program uses cpu time or   |
  3064. |   wall-clock time for timing.  for tournament play,      |
  3065. |   it is safer to use wall-clock timing, for testing it   |
  3066. |   may be more consistent to use cpu timing if the        |
  3067. |   machine is used for other things concurrently with the |
  3068. |   tests being run.                                       |
  3069. |                                                          |
  3070. |   "time" is also used to set the basic search timing     |
  3071. |   controls.  the general form of the command is as       |
  3072. |   follows:                                               |
  3073. |                                                          |
  3074. |     time nmoves/ntime/[nmoves/ntime]/[increment]         |
  3075. |                                                          |
  3076. |   nmoves/ntime represents a traditional first time       |
  3077. |   control when nmoves is an integer representing the     |
  3078. |   number of moves and ntime is the total time allowed    |
  3079. |   for these moves.  the [optional] nmoves/ntime is a     |
  3080. |   traditional secondary time control.  increment is a    |
  3081. |   feature related to ics play and emulates the fischer   |
  3082. |   clock where "increment" is added to the time left      |
  3083. |   after each move is made.                               |
  3084. |                                                          |
  3085. |   as an alternative, nmoves can be "sd" which represents |
  3086. |   a "sudden death" time control of the remainder of the  |
  3087. |   game played in ntime.  the optional secondary time     |
  3088. |   control can be a sudden-death time control, as in the  |
  3089. |   following example:                                     |
  3090. |                                                          |
  3091. |     time 60/30/sd/30                                     |
  3092. |                                                          |
  3093. |   this sets 60 moves in 30 minutes, then game in 30      |
  3094. |   additional minutes.  an increment can be added if      |
  3095. |   desired.                                               |
  3096. |                                                          |
  3097.  ----------------------------------------------------------
  3098. */
  3099.   else if (OptionMatch("time",*args)) {
  3100.     if (ics || xboard) {
  3101.       tc_time_remaining=atoi(args[1]);
  3102.       if (log_file && time_limit>99)
  3103.         fprintf(log_file,"time remaining: %s (crafty).\n",
  3104.                 DisplayTime(tc_time_remaining));
  3105.     }
  3106.     else {
  3107.       if (thinking || pondering) return(2);
  3108.       if (nargs == 2) {
  3109.         if (!strcmp("cpu",args[1])) {
  3110.           time_type=cpu;
  3111.           Print(4095,"using cpu time\n");
  3112.         }
  3113.         else if (!strcmp("elapsed",args[1])) {
  3114.           time_type=elapsed;
  3115.           Print(4095,"using elapsed time\n");
  3116.         }
  3117.         else printf("usage:  time cpu|elapsed|<controls>\n");
  3118.       }
  3119.       else {
  3120.         tc_moves=60;
  3121.         tc_time=180000;
  3122.         tc_moves_remaining=60;
  3123.         tc_time_remaining=180000;
  3124.         tc_time_remaining_opponent=180000;
  3125.         tc_secondary_moves=60;
  3126.         tc_secondary_time=180000;
  3127.         tc_increment=0;
  3128.         tc_sudden_death=0;
  3129. /*
  3130.   first let's pick off the basic time control (moves/minutes)
  3131. */
  3132.         if (nargs > 1)
  3133.           if (!strcmp(args[1],"sd")) {
  3134.             tc_sudden_death=1;
  3135.             tc_moves=1000;
  3136.           }
  3137.         if (nargs > 2) {
  3138.           tc_moves=atoi(args[1]);
  3139.           tc_time=atoi(args[2])*100;
  3140.         }
  3141. /*
  3142.   now let's pick off the secondary time control (moves/minutes)
  3143. */
  3144.         tc_secondary_time=tc_time;
  3145.         tc_secondary_moves=tc_moves;
  3146.         if (nargs > 3)
  3147.           if (!strcmp(args[3],"sd")) {
  3148.             tc_sudden_death=2;
  3149.             tc_secondary_moves=1000;
  3150.           }
  3151.         if (nargs > 4) {
  3152.           tc_secondary_moves=atoi(args[3]);
  3153.           tc_secondary_time=atoi(args[4])*100;
  3154.         }
  3155.         if (nargs > 5)
  3156.           tc_increment=atoi(args[5])*100;
  3157.         tc_time_remaining=tc_time;
  3158.         tc_time_remaining_opponent=tc_time;
  3159.         tc_moves_remaining=tc_moves;
  3160.         if (!tc_sudden_death) {
  3161.           Print(4095,"%d moves/%d minutes primary time control\n",
  3162.                 tc_moves, tc_time/100);
  3163.           Print(4095,"%d moves/%d minutes secondary time control\n",
  3164.                 tc_secondary_moves, tc_secondary_time/100);
  3165.           if (tc_increment) Print(4095,"increment %d seconds.\n",tc_increment/100);
  3166.         }
  3167.         else if (tc_sudden_death == 1) {
  3168.           Print(4095," game/%d minutes primary time control\n",
  3169.                 tc_time/100);
  3170.           if (tc_increment) Print(4095,"increment %d seconds.\n",tc_increment/100);
  3171.         }
  3172.         else if (tc_sudden_death == 2) {
  3173.           Print(4095,"%d moves/%d minutes primary time control\n",
  3174.                 tc_moves, tc_time/100);
  3175.           Print(4095,"game/%d minutes secondary time control\n",
  3176.                 tc_secondary_time/100);
  3177.           if (tc_increment) Print(4095,"increment %d seconds.\n",tc_increment/100);
  3178.         }
  3179.         tc_time*=60;
  3180.         tc_time_remaining*=60;
  3181.         tc_time_remaining_opponent*=60;
  3182.         tc_secondary_time*=60;
  3183.         tc_safety_margin=tc_time/6;
  3184.       }
  3185.     }
  3186.   }
  3187. /*
  3188.  ----------------------------------------------------------
  3189. |                                                          |
  3190. |   "timeleft" command comes from the custom ICS interface |
  3191. |   and indicates how much time is left for white and for  |
  3192. |   black.                                                 |
  3193. |                                                          |
  3194.  ----------------------------------------------------------
  3195. */
  3196.   else if (OptionMatch("timeleft",*args)) {
  3197.     if (nargs < 3) {
  3198.       printf("usage:  timeleft <wtime> <btime>\n");
  3199.       return(1);
  3200.     }
  3201.     if (crafty_is_white) {
  3202.       tc_time_remaining=atoi(args[1]);
  3203.       tc_time_remaining_opponent=atoi(args[2]);
  3204.     }
  3205.     else {
  3206.       tc_time_remaining_opponent=atoi(args[1]);
  3207.       tc_time_remaining=atoi(args[2]);
  3208.     }
  3209.     if (log_file) {
  3210.       fprintf(log_file,"time remaining: %s (crafty).\n",
  3211.                        DisplayTime(tc_time_remaining));
  3212.       fprintf(log_file,"time remaining: %s (opponent).\n",
  3213.                        DisplayTime(tc_time_remaining_opponent));
  3214.     }
  3215.   }
  3216. /*
  3217.  ----------------------------------------------------------
  3218. |                                                          |
  3219. |   "trace" command sets the search trace level which will |
  3220. |   dump the tree as it is searched.                       |
  3221. |                                                          |
  3222.  ----------------------------------------------------------
  3223. */
  3224.   else if (OptionMatch("trace",*args)) {
  3225. #if defined(FAST)
  3226.     printf("Sorry, but I can't display traces when compiled with -DFAST\n");
  3227. #else
  3228.     if (nargs < 2) {
  3229.       printf("usage:  trace <depth>\n");
  3230.       return(1);
  3231.     }
  3232.     trace_level=atoi(args[1]);
  3233.     printf("trace=%d\n",trace_level);
  3234. #endif
  3235.   }
  3236. /*
  3237.  ----------------------------------------------------------
  3238. |                                                          |
  3239. |   "tt" command is used to test time control logic.       |
  3240. |                                                          |
  3241.  ----------------------------------------------------------
  3242. */
  3243.   else if (OptionMatch("tt",*args)) {
  3244.     int time_used;
  3245.     do {
  3246.       TimeSet(think);
  3247.       printf("time used? ");
  3248.       fflush(stdout);
  3249.       fgets(buffer,128,stdin);
  3250.       if (strlen(buffer)) time_used=atoi(buffer);
  3251.       else time_used=time_limit;
  3252.       TimeAdjust(time_used,opponent);
  3253.       TimeAdjust(time_used,crafty);
  3254.       sprintf(buffer,"clock");
  3255.       Option(tree);
  3256.       move_number++;
  3257.     } while (time_used >= 0);
  3258.   }
  3259. /*
  3260.  ----------------------------------------------------------
  3261. |                                                          |
  3262. |   "undo" command backs up 1/2 move, which leaves the     |
  3263. |   opposite side on move. [xboard compatibility]          |
  3264. |                                                          |
  3265.  ----------------------------------------------------------
  3266. */
  3267.   else if (!strcmp("undo",*args)) {
  3268.     if (thinking || pondering) return(2);
  3269.     wtm=ChangeSide(wtm);
  3270.     if (ChangeSide(wtm)) move_number--;
  3271.     sprintf(buffer,"reset %d",move_number);
  3272.     (void) Option(tree);
  3273.   }
  3274. /*
  3275.  ---------------------------------------------------------------
  3276. |                                                               |
  3277. |   "usage" command controls the time usage multiple factors    |
  3278. |  used in the game  - percntage increase or decrease in time   |
  3279. |  used up front.  Enter a number between 1 to 100 for the      |
  3280. |  % decrease to increase - although other time limitations     !
  3281. | controls may kick in.  negatives work as well, may be used    |
  3282. | in crafty.rc                                                  |
  3283. |                                                               |
  3284.  ---------------------------------------------------------------
  3285. */
  3286.  else if (OptionMatch("usage",*args)) {
  3287.     if (nargs < 2) {
  3288.       printf("usage:  usage <percentage>\n");
  3289.       return(1);
  3290.     }
  3291.     usage_level=atoi(args[1]);
  3292.     if (usage_level > 50) usage_level=50;
  3293.     else if (usage_level < -50) usage_level=-50;
  3294.     Print(4095,"time usage up front set to %d percent increase/(-)decrease.\n",
  3295.           usage_level);
  3296.   }
  3297. /*
  3298.  ----------------------------------------------------------
  3299. |                                                          |
  3300. |   "whisper" command sets whisper mode for ICS.  =1 will  |
  3301. |   whisper mate announcements, =2 will whisper scores and |
  3302. |   other info, =3 will whisper scores and PV, =4 adds the |
  3303. |   list of book moves, =5 displays the PV after each      |
  3304. |   iteration completes, and =6 displays the PV each time  |
  3305. |   it changes in an iteration.                            |
  3306. |                                                          |
  3307.  ----------------------------------------------------------
  3308. */
  3309.   else if (OptionMatch("whisper",*args)) {
  3310.     if (nargs < 2) {
  3311.       printf("usage:  whisper <level>\n");
  3312.       return(1);
  3313.     }
  3314.     whisper=atoi(args[1]);
  3315.   }
  3316. /*
  3317.  ----------------------------------------------------------
  3318. |                                                          |
  3319. |   "wild" command sets up an ICS wild position (only 7 at |
  3320. |   present, but any can be added easily, except for those |
  3321. |   that Crafty simply can't play (two kings, invisible    |
  3322. |   pieces, etc.)                                          |
  3323. |                                                          |
  3324.  ----------------------------------------------------------
  3325. */
  3326.   else if (OptionMatch("wild",*args)) {
  3327.     int i;
  3328.  
  3329.     if (nargs < 2) {
  3330.       printf("usage:  wild <value>\n");
  3331.       return(1);
  3332.     }
  3333.     i=atoi(args[1]);
  3334.     switch (i) {
  3335.     case 7:
  3336.       strcpy(buffer,"setboard 4k/5ppp/////PPP/3K/ w");
  3337.       (void) Option(tree);
  3338.       break;
  3339.     default:
  3340.       printf("sorry, only wild7 implemented at present\n");
  3341.       break;
  3342.     }
  3343.   }
  3344. /*
  3345.  ----------------------------------------------------------
  3346. |                                                          |
  3347. |   "white" command sets white to move (wtm).              |
  3348. |                                                          |
  3349.  ----------------------------------------------------------
  3350. */
  3351.   else if (OptionMatch("white",*args)) {
  3352.     if (thinking || pondering) return(2);
  3353.     ponder_move=0;
  3354.     last_pv.path_iteration_depth=0;
  3355.     last_pv.path_length=0;
  3356.     if (!wtm) Pass();
  3357.     force=0;
  3358.   }
  3359. /*
  3360.  ----------------------------------------------------------
  3361. |                                                          |
  3362. |  "xboard" command is normally invoked from main() via    |
  3363. |  the xboard command-line option.  it sets proper         |
  3364. |  defaults for ics/Xboard interface requirements.         |
  3365. |                                                          |
  3366.  ----------------------------------------------------------
  3367. */
  3368.   else if (OptionMatch("xboard",*args) || OptionMatch("winboard",*args)) {
  3369.     if (!xboard) {
  3370.       signal(SIGINT,SIG_IGN);
  3371.       xboard=1;
  3372.       display_options&=4095-1-2-4-8-16-32-128;
  3373.       ansi=0;
  3374.       printf("\n");
  3375.       printf("kibitz Hello from Crafty v%s! (%d cpus)\n",version,CPUS);
  3376.       printf("tellics set 1 Crafty v%s (%d cpus)\n",version,CPUS);
  3377.       fflush(stdout);
  3378.     }
  3379.   }
  3380. /*
  3381.  ----------------------------------------------------------
  3382. |                                                          |
  3383. |  "?" command does nothing, but since this is the "move   |
  3384. |  now" keystroke, if crafty is not searching, this will   |
  3385. |  simply "wave it off" rather than produce an error.      |
  3386. |                                                          |
  3387.  ----------------------------------------------------------
  3388. */
  3389.   else if (OptionMatch("?",*args)) {
  3390.   }
  3391. /*
  3392.  ----------------------------------------------------------
  3393. |                                                          |
  3394. |   unknown command, it must be a move.                    |
  3395. |                                                          |
  3396.  ----------------------------------------------------------
  3397. */
  3398.   else
  3399.     return(0);
  3400. /*
  3401.  ----------------------------------------------------------
  3402. |                                                          |
  3403. |   command executed, return for another.                  |
  3404. |                                                          |
  3405.  ----------------------------------------------------------
  3406. */
  3407.     return(1);
  3408. }
  3409.  
  3410. /*
  3411. ********************************************************************************
  3412. *                                                                              *
  3413. *   OptionMatch() is used to recognize user commands.  it requires that the    *
  3414. *   command (text input which is the *2nd parameter* conform to the following  *
  3415. *   simple rules:                                                              *
  3416. *                                                                              *
  3417. *     1.  the input must match the command, starting at the left-most          *
  3418. *         character.                                                           *
  3419. *     2.  if the command starts with a sequence of characters that could       *
  3420. *         be interpreted as a chess move as well (re for reset and/or rook     *
  3421. *         to the e-file) then the input must match enough of the command       *
  3422. *         to get past the ambiguity (res would be minimum we will accept       *
  3423. *         for the reset command.)                                              *
  3424. *                                                                              *
  3425. ********************************************************************************
  3426. */
  3427. int OptionMatch(char *command, char *input)
  3428. {
  3429. /*
  3430.  ----------------------------------------------------------
  3431. |                                                          |
  3432. |   check for the obvious exact match first.               |
  3433. |                                                          |
  3434.  ----------------------------------------------------------
  3435. */
  3436.   if (!strcmp(command,input)) return(1);
  3437. /*
  3438.  ----------------------------------------------------------
  3439. |                                                          |
  3440. |   now use strstr() to see if "input" is in "command."    |
  3441. |   the first requirement is that input matches command    |
  3442. |   starting at the very left-most character;              |
  3443. |                                                          |
  3444.  ----------------------------------------------------------
  3445. */
  3446.   if (strstr(command,input) == command) return(1);
  3447.   return(0);
  3448. }
  3449.  
  3450. void OptionPerft(TREE *tree, int ply,int depth,int wtm)
  3451. {
  3452.   int i, *mv;
  3453.  
  3454.   tree->last[ply]=GenerateCaptures(tree, ply, wtm, tree->last[ply-1]);
  3455.   tree->last[ply]=GenerateNonCaptures(tree, ply, wtm, tree->last[ply]);
  3456.   for (mv=tree->last[ply-1];mv<tree->last[ply];mv++) {
  3457.     MakeMove(tree,ply,*mv,wtm);
  3458.     if (!Check(wtm)) {
  3459.       if (ply <= trace_level) {
  3460.         for (i=1;i<ply;i++) printf("  ");
  3461.         printf("%s\n", OutputMove(tree,*mv,ply,wtm));
  3462.       }
  3463.       total_moves++;
  3464.       if (depth-1) OptionPerft(tree,ply+1,depth-1,ChangeSide(wtm));
  3465.     }
  3466.     UnMakeMove(tree,ply,*mv,wtm);
  3467.   }
  3468. }
  3469.