Subversion Repositories Games.Chess Giants

Rev

Rev 108 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "chess.h"
  2. #include "data.h"
  3. /* last modified 02/23/14 */
  4. /*
  5.  *******************************************************************************
  6.  *                                                                             *
  7.  *   Ponder() is the driver for "pondering" (thinking on the opponent's time.) *
  8.  *   its operation is simple:  Find a predicted move by (a) taking the second  *
  9.  *   move from the principal variation, or (b) call lookup to see if it finds  *
  10.  *   a suggested move from the transposition table.  Then, make this move and  *
  11.  *   do a search from the resulting position.  While pondering, one of three   *
  12.  *   things can happen:  (1) A move is entered, and it matches the predicted   *
  13.  *   move.  We then switch from pondering to thinking and search as normal;    *
  14.  *   (2) A move is entered, but it does not match the predicted move.  We then *
  15.  *   abort the search, unmake the pondered move, and then restart with the move*
  16.  *   entered.  (3) A command is entered.  If it is a simple command, it can be *
  17.  *   done without aborting the search or losing time.  If not, we abort the    *
  18.  *   search, execute the command, and then attempt to restart pondering if the *
  19.  *   command didn't make that impossible.                                      *
  20.  *                                                                             *
  21.  *******************************************************************************
  22.  */
  23. int Ponder(int wtm) {
  24.   int dalpha = -999999, dbeta = 999999, i, *n_ponder_moves, *mv;
  25.   int save_move_number, tlom, value;
  26.   TREE *const tree = block[0];
  27.  
  28. /*
  29.  ************************************************************
  30.  *                                                          *
  31.  *  First, let's check to see if pondering is allowed, or   *
  32.  *  if we should avoid pondering on this move since it is   *
  33.  *  the first move of a game, or if the game is over, or    *
  34.  *  "force" mode is active, or there is input in the queue  *
  35.  *  that needs to be read and processed.                    *
  36.  *                                                          *
  37.  ************************************************************
  38.  */
  39.   if (!ponder || force || over || CheckInput())
  40.     return 0;
  41.   save_move_number = move_number;
  42. /*
  43.  ************************************************************
  44.  *                                                          *
  45.  *  Check the ponder move for legality.  If it is not a     *
  46.  *  legal move, we have to take action to find something to *
  47.  *  ponder.                                                 *
  48.  *                                                          *
  49.  ************************************************************
  50.  */
  51.   strcpy_s(hint, sizeof (hint), "none"); // Pierre-Marie Baty -- use safe version
  52.   if (ponder_move) {
  53.     if (!VerifyMove(tree, 1, wtm, ponder_move)) {
  54.       ponder_move = 0;
  55.       Print(4095, "ERROR.  ponder_move is illegal (1).\n");
  56.       Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
  57.       Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
  58.     }
  59.   }
  60. /*
  61.  ************************************************************
  62.  *                                                          *
  63.  *  First attempt, do a hash probe.  However, since a hash  *
  64.  *  collision is remotely possible, we still need to verify *
  65.  *  that the transposition/refutation best move is actually *
  66.  *  legal.                                                  *
  67.  *                                                          *
  68.  ************************************************************
  69.  */
  70.   if (!ponder_move) {
  71.     (void) HashProbe(tree, 0, 0, wtm, dalpha, dbeta, &value);
  72.     if (tree->hash_move[0])
  73.       ponder_move = tree->hash_move[0];
  74.     if (ponder_move) {
  75.       if (!VerifyMove(tree, 1, wtm, ponder_move)) {
  76.         Print(4095, "ERROR.  ponder_move is illegal (2).\n");
  77.         Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
  78.         ponder_move = 0;
  79.       }
  80.     }
  81.   }
  82. /*
  83.  ************************************************************
  84.  *                                                          *
  85.  *  Second attempt.  If that didn't work, then we try what  *
  86.  *  I call a "puzzling" search.  Which is simply a shorter  *
  87.  *  time-limit search for the other side, to find something *
  88.  *  to ponder.                                              *
  89.  *                                                          *
  90.  ************************************************************
  91.  */
  92.   if (!ponder_move) {
  93.     TimeSet(puzzle);
  94.     if (time_limit < 20)
  95.       return 0;
  96.     puzzling = 1;
  97.     tree->status[1] = tree->status[0];
  98.     Print(128, "              puzzling over a move to ponder.\n");
  99.     last_pv.pathl = 0;
  100.     last_pv.pathd = 0;
  101.     for (i = 0; i < MAXPLY; i++) {
  102.       tree->killers[i].move1 = 0;
  103.       tree->killers[i].move2 = 0;
  104.     }
  105.     (void) Iterate(wtm, puzzle, 0);
  106.     for (i = 0; i < MAXPLY; i++) {
  107.       tree->killers[i].move1 = 0;
  108.       tree->killers[i].move2 = 0;
  109.     }
  110.     puzzling = 0;
  111.     if (tree->pv[0].pathl)
  112.       ponder_move = tree->pv[0].path[1];
  113.     if (!ponder_move)
  114.       return 0;
  115.     for (i = 1; i < (int) tree->pv[0].pathl; i++)
  116.       last_pv.path[i] = tree->pv[0].path[i + 1];
  117.     last_pv.pathl = tree->pv[0].pathl - 1;
  118.     last_pv.pathd = 0;
  119.     if (!VerifyMove(tree, 1, wtm, ponder_move)) {
  120.       ponder_move = 0;
  121.       Print(4095, "ERROR.  ponder_move is illegal (3).\n");
  122.       Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
  123.       return 0;
  124.     }
  125.   }
  126. /*
  127.  ************************************************************
  128.  *                                                          *
  129.  *  Display the move we are going to "ponder".              *
  130.  *                                                          *
  131.  ************************************************************
  132.  */
  133.   if (wtm)
  134.     Print(128, "White(%d): %s [pondering]\n", move_number, OutputMove(tree,
  135.             ponder_move, 0, wtm));
  136.   else
  137.     Print(128, "Black(%d): %s [pondering]\n", move_number, OutputMove(tree,
  138.             ponder_move, 0, wtm));
  139.   sprintf_s(hint, sizeof (hint), "%s", OutputMove(tree, ponder_move, 0, wtm)); // Pierre-Marie Baty -- use safe version
  140.   if (post)
  141.     printf("Hint: %s\n", hint);
  142. /*
  143.  ************************************************************
  144.  *                                                          *
  145.  *  Set the ponder move list and eliminate illegal moves.   *
  146.  *  This list is used to test the move entered while we are *
  147.  *  pondering, since we need a move list for the input      *
  148.  *  screening process.                                      *
  149.  *                                                          *
  150.  ************************************************************
  151.  */
  152.   n_ponder_moves = GenerateCaptures(tree, 0, wtm, ponder_moves);
  153.   num_ponder_moves =
  154.       GenerateNoncaptures(tree, 0, wtm, n_ponder_moves) - ponder_moves;
  155.   for (mv = ponder_moves; mv < ponder_moves + num_ponder_moves; mv++) {
  156.     MakeMove(tree, 0, *mv, wtm);
  157.     if (Check(wtm)) {
  158.       UnmakeMove(tree, 0, *mv, wtm);
  159.       *mv = 0;
  160.     } else
  161.       UnmakeMove(tree, 0, *mv, wtm);
  162.   }
  163. /*
  164.  ************************************************************
  165.  *                                                          *
  166.  *  Now, perform an iterated search, but with the special   *
  167.  *  "pondering" flag set which changes the time controls    *
  168.  *  since there is no need to stop searching until the      *
  169.  *  opponent makes a move.                                  *
  170.  *                                                          *
  171.  ************************************************************
  172.  */
  173.   MakeMove(tree, 0, ponder_move, wtm);
  174.   tree->rep_list[++(tree->rep_index)] = HashKey;
  175.   tlom = last_opponent_move;
  176.   last_opponent_move = ponder_move;
  177.   if (kibitz)
  178.     strcpy_s(kibitz_text, sizeof (kibitz_text), "n/a"); // Pierre-Marie Baty -- use safe version
  179.   thinking = 0;
  180.   pondering = 1;
  181.   if (!wtm)
  182.     move_number++;
  183.   ponder_value = Iterate(Flip(wtm), think, 0);
  184.   tree->rep_index--;
  185.   move_number = save_move_number;
  186.   pondering = 0;
  187.   thinking = 0;
  188.   last_opponent_move = tlom;
  189.   UnmakeMove(tree, 0, ponder_move, wtm);
  190. /*
  191.  ************************************************************
  192.  *                                                          *
  193.  *  Search completed. the possible return values are:       *
  194.  *                                                          *
  195.  *  (0) No pondering was done, period.                      *
  196.  *                                                          *
  197.  *  (1) Pondering was done, opponent made the predicted     *
  198.  *      move, and we searched until time ran out in a       *
  199.  *      normal manner.                                      *
  200.  *                                                          *
  201.  *  (2) Pondering was done, but the ponder search           *
  202.  *      terminated due to either finding a mate, or the     *
  203.  *      maximum search depth was reached.  The result of    *
  204.  *      this ponder search are valid, but only if the       *
  205.  *      opponent makes the correct (predicted) move.        *
  206.  *                                                          *
  207.  *  (3) Pondering was done, but the opponent either made    *
  208.  *      a different move, or entered a command that has to  *
  209.  *      interrupt the pondering search before the command   *
  210.  *      (or move) can be processed.  This forces Main() to  *
  211.  *      avoid reading in a move/command since one has been  *
  212.  *      read into the command buffer already.               *
  213.  *                                                          *
  214.  ************************************************************
  215.  */
  216.   if (input_status == 1)
  217.     return 1;
  218.   if (input_status == 2)
  219.     return 3;
  220.   return 2;
  221. }
  222.