- #include "chess.h" 
- #include "data.h" 
- /* last modified 08/03/16 */ 
- /* 
-  ******************************************************************************* 
-  *                                                                             * 
-  *   Quiece() is the recursive routine used to implement the quiescence        * 
-  *   search part of the alpha/beta negamax search.  It performs the following  * 
-  *   functions:                                                                * 
-  *                                                                             * 
-  *   (1) It computes a stand-pat score, which gives the side-on-move the       * 
-  *   choice of standing pat and not playing any move at all and just accepting * 
-  *   the current static evaluation, or else it may try captures and/or         * 
-  *   checking moves to see if it can improve the stand-pat score by making a   * 
-  *   move that leads to some sort of positional or material gain.              * 
-  *                                                                             * 
-  *   (2) The first phase is to generate all possible capture moves and then    * 
-  *   sort them into descending using the value of the captured piece and the   * 
-  *   complemented value of the capturing piece.  This is the classic MVV/LVA   * 
-  *   ordering approach that removes heavy pieces first in an attempt to reduce * 
-  *   the size of the sub-tree these pieces produce.                            * 
-  *                                                                             * 
-  *   (3) When we get ready to actually search each capture, we analyze each    * 
-  *   move to see if it appears reasonable.  Small pieces can capture larger    * 
-  *   ones safely, ditto for equal exchanges.  For the rest, we use SEE() to    * 
-  *   compute the SEE score.  If this is less than zero, we do not search this  * 
-  *   move at all to avoid wasting time, since a losing capture rarely helps    * 
-  *   improve the score in the q-search.  The goal here is to find a capture    * 
-  *   that improves on the stand-pat score and gets us closer to a position     * 
-  *   that we would describe as "quiet" or "static".                            * 
-  *                                                                             * 
-  *   (4) If the parameter "checks" is non-zero, then after searching the       * 
-  *   captures, we generate checking moves and search those.  This value also   * 
-  *   slightly changes the way captures are searched, since those that are also * 
-  *   checks result in calling QuiesceEvasions() which evades checks to see if  * 
-  *   the check is actually a mate.  This means that we have one layer of full- * 
-  *   width search to escape checks and do not allow a stand-pat which would    * 
-  *   hide the effect of the check completely.                                  * 
-  *                                                                             * 
-  ******************************************************************************* 
-  */ 
- int Quiesce(TREE * RESTRICT tree, int ply, int wtm, int alpha, int beta, 
-     int checks) { 
-   unsigned *next, *movep; 
-   int original_alpha = alpha, value, repeat; 
-   
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Initialize.                                             * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   if (ply >= MAXPLY - 1) 
-     return beta; 
- #if defined(NODES) 
-   if (search_nodes && --temp_search_nodes <= 0) { 
-     abort_search = 1; 
-     return 0; 
-   } 
- #endif 
-   if (tree->thread_id == 0) 
-     next_time_check--; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Check for draw by repetition, which includes 50 move    * 
-  *  draws also.  This is only done at the first ply of the  * 
-  *  quiescence search since we are following checking moves * 
-  *  as well.  The parameter "checks" passed in is "1" for   * 
-  *  that particular case only (when called from Search()).  * 
-  *  all other calls (from inside Quiesce()) pass a value of * 
-  *  zero so that additional plies of checks are not tried.  * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   if (checks) { 
-     repeat = Repeat(tree, ply); 
-     if (repeat) { 
-       value = DrawScore(wtm); 
-       if (value < beta) 
-         SavePV(tree, ply, repeat); 
- #if defined(TRACE) 
-       if (ply <= trace_level) 
-         printf("draw by repetition detected, ply=%d.\n",-  ply );
 
- #endif 
-       return value; 
-     } 
-   } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Now call Evaluate() to produce the "stand-pat" score    * 
-  *  that will be returned if no capture is acceptable.  If  * 
-  *  this score is > alpha and < beta, then we also have to  * 
-  *  save the path to this node as it is the PV that leads   * 
-  *  to this score.                                          * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   value = Evaluate(tree, ply, wtm, alpha, beta); 
- #if defined(TRACE) 
-   if (ply <= trace_level) 
-     Trace(tree, ply, value, wtm, alpha, beta, "Quiesce", serial, EVALUATION, 
-         0); 
- #endif 
-   if (value > alpha) { 
-     if (value >= beta) 
-       return value; 
-     alpha = value; 
-     tree->pv[ply].pathl = ply; 
-     tree->pv[ply].pathh = 0; 
-     tree->pv[ply].pathd = iteration; 
-   } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Generate captures and sort them based on simple MVV/LVA * 
-  *  order.  We simply try to capture the most valuable      * 
-  *  piece possible, using the least valuable attacker       * 
-  *  possible, to get rid of heavy pieces quickly and reduce * 
-  *  the overall size of the tree.                           * 
-  *                                                          * 
-  *  Note that later we use the value of the capturing       * 
-  *  piece, the value of the captured piece, and possibly    * 
-  *  SEE() to exclude captures that appear to lose material, * 
-  *  but we delay expending this effort as long as possible, * 
-  *  since beta cutoffs make it unnecessary to search all of * 
-  *  these moves anyway.                                     * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   tree->last[ply] = GenerateCaptures(tree, ply, wtm, tree->last[ply - 1]); 
-   for (movep = tree->last[ply - 1]; movep < tree->last[ply]; movep++) { 
-     if (Captured(*movep) == king) 
-       return beta; 
-     *movep += MVV_LVA[Captured(*movep)][Piece(*movep)]; 
-   } 
-   if (!checks && tree->last[ply] == tree->last[ply - 1]) { 
-     if (alpha != original_alpha) { 
-       tree->pv[ply - 1] = tree->pv[ply]; 
-       tree->pv[ply - 1].path[ply - 1] = tree->curmv[ply - 1]; 
-     } 
-     return value; 
-   } 
-   NextSort(tree, ply); 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Iterate through the move list and search the resulting  * 
-  *  positions.  Now that we are ready to actually search    * 
-  *  the set of capturing moves, we try three quick tests to * 
-  *  see if the move should be excluded because it appears   * 
-  *  to lose material.                                       * 
-  *                                                          * 
-  *  (1) If the capturing piece is not more valuable than    * 
-  *  the captured piece, then the move can't lose material   * 
-  *  and should be searched.                                 * 
-  *                                                          * 
-  *  (2) If the capture removes the last opponent piece, we  * 
-  *  always search this kind of capture since this can be    * 
-  *  the move the allows a passed pawn to promote when the   * 
-  *  opponent has no piece to catch it.                      * 
-  *                                                          * 
-  *  (3) Otherwise, If the capturing piece is more valuable  * 
-  *  than the captured piece, we use SEE() to determine if   * 
-  *  the capture is losing or not so that we don't search    * 
-  *  hopeless moves.                                         * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   for (next = tree->last[ply - 1]; next < tree->last[ply]; next++) { 
-     tree->curmv[ply] = Move(*next); 
-     if (pcval[Piece(tree->curmv[ply])] > pcval[Captured(tree->curmv[ply])] && 
-         TotalPieces(Flip(wtm), occupied) 
-         - p_vals[Captured(tree->curmv[ply])] > 0 && 
-         SEE(tree, wtm, tree->curmv[ply]) < 0) 
-       continue; 
- #if defined(TRACE) 
-     if (ply <= trace_level) 
-       Trace(tree, ply, 0, wtm, alpha, beta, "Quiesce", serial, CAPTURES, 
-           next - tree->last[ply - 1] + 1); 
- #endif 
-     MakeMove(tree, ply, wtm, tree->curmv[ply]); 
-     tree->nodes_searched++; 
-     if (!checks) 
-       value = -Quiesce(tree, ply + 1, Flip(wtm), -beta, -alpha, 0); 
-     else if (!Check(wtm)) { 
-       if (Check(Flip(wtm))) { 
-         tree->qchecks_done++; 
-         value = -QuiesceEvasions(tree, ply + 1, Flip(wtm), -beta, -alpha); 
-       } else 
-         value = -Quiesce(tree, ply + 1, Flip(wtm), -beta, -alpha, 0); 
-     } 
-     UnmakeMove(tree, ply, wtm, tree->curmv[ply]); 
-     if (abort_search || tree->stop) 
-       return 0; 
-     if (value > alpha) { 
-       if (value >= beta) 
-         return value; 
-       alpha = value; 
-     } 
-   } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  The next block of code is only executed if the checks   * 
-  *  parameter is non-zero, otherwise we skip this and exit  * 
-  *  with no further searching.                              * 
-  *                                                          * 
-  *  Generate just the moves (non-captures) that give check  * 
-  *  and search the ones that SEE() says are safe.  Subtle   * 
-  *  trick:  we discard the captures left over from the      * 
-  *  above search since we labeled them "losing moves."      * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   if (checks) { 
-     tree->last[ply] = GenerateChecks(tree, wtm, tree->last[ply - 1]); 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Iterate through the move list and search the resulting  * 
-  *  positions.  We take them in the normal order that       * 
-  *  GenerateChecks() provides.                              * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-     for (next = tree->last[ply - 1]; next < tree->last[ply]; next++) { 
-       tree->curmv[ply] = Move(*next); 
-       if (SEE(tree, wtm, tree->curmv[ply]) >= 0) { 
- #if defined(TRACE) 
-         if (ply <= trace_level) 
-           Trace(tree, ply, 0, wtm, alpha, beta, "Quiesce+checks", serial, 
-               REMAINING, next - tree->last[ply - 1] + 1); 
- #endif 
-         MakeMove(tree, ply, wtm, tree->curmv[ply]); 
-         tree->nodes_searched++; 
-         if (!Check(wtm)) { 
-           tree->qchecks_done++; 
-           value = -QuiesceEvasions(tree, ply + 1, Flip(wtm), -beta, -alpha); 
-         } 
-         UnmakeMove(tree, ply, wtm, tree->curmv[ply]); 
-         if (abort_search || tree->stop) 
-           return 0; 
-         if (value > alpha) { 
-           if (value >= beta) 
-             return value; 
-           alpha = value; 
-         } 
-       } 
-     } 
-   } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  All moves have been searched.  Return the search result * 
-  *  that was found.  If the result is not the original      * 
-  *  alpha score, then we need to back up the PV that is     * 
-  *  associated with this score.                             * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   if (alpha != original_alpha) { 
-     tree->pv[ply - 1] = tree->pv[ply]; 
-     tree->pv[ply - 1].path[ply - 1] = tree->curmv[ply - 1]; 
-   } 
-   return alpha; 
- } 
-   
- /* last modified 08/03/16 */ 
- /* 
-  ******************************************************************************* 
-  *                                                                             * 
-  *   QuiesceEvasions() is the recursive routine used to implement the alpha/   * 
-  *   beta negamax quiescence search.  The primary function here is to escape a * 
-  *   check that was delivered by Quiesce() at the previous ply.  We do not     * 
-  *   have the usual "stand pat" option because we have to find a legal move to * 
-  *   prove we have not been checkmated.                                        * 
-  *                                                                             * 
-  *   QuiesceEvasions() uses the legal move generator (GenerateCheckEvasions()) * 
-  *   to produce only the set of legal moves that escape check.  We try those   * 
-  *   in the the order they are generated since we are going to try them all    * 
-  *   unless we get a fail-high.                                                * 
-  *                                                                             * 
-  ******************************************************************************* 
-  */ 
- int QuiesceEvasions(TREE * RESTRICT tree, int ply, int wtm, int alpha, 
-     int beta) { 
-   int original_alpha, value, moves_searched = 0, order, repeat; 
-   
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Initialize.                                             * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   if (ply >= MAXPLY - 1) 
-     return beta; 
- #if defined(NODES) 
-   if (search_nodes && --temp_search_nodes <= 0) { 
-     abort_search = 1; 
-     return 0; 
-   } 
-   if (tree->thread_id == 0) 
-     next_time_check--; 
- #endif 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Check for draw by repetition, which includes 50 move    * 
-  *  draws also.                                             * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   repeat = Repeat(tree, ply); 
-   if (repeat) { 
-     value = DrawScore(wtm); 
-     if (value < beta) 
-       SavePV(tree, ply, repeat); 
- #if defined(TRACE) 
-     if (ply <= trace_level) 
-       printf("draw by repetition detected, ply=%d.\n",-  ply );
 
- #endif 
-     return value; 
-   } 
-   original_alpha = alpha; 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  Iterate through the move list and search the resulting  * 
-  *  positions.  These moves are searched in the order that  * 
-  *  GenerateEvasions() produces them.  No hash move is      * 
-  *  possible since we don't do probes in Quiesce().  We do  * 
-  *  clear the hash move before we start selecting moves so  * 
-  *  that we don't search a bogus move from a different      * 
-  *  position.                                               * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   tree->hash_move[ply] = 0; 
-   tree->next_status[ply].phase = HASH; 
-   while ((order = NextMove(tree, ply, 0, wtm, 1))) { 
- #if defined(TRACE) 
-     if (ply <= trace_level) 
-       Trace(tree, ply, 0, wtm, alpha, beta, "QuiesceEvasions", serial, 
-           tree->phase[ply], order); 
- #endif 
-     moves_searched++; 
-     MakeMove(tree, ply, wtm, tree->curmv[ply]); 
-     tree->nodes_searched++; 
-     value = -Quiesce(tree, ply + 1, Flip(wtm), -beta, -alpha, 0); 
-     UnmakeMove(tree, ply, wtm, tree->curmv[ply]); 
-     if (abort_search || tree->stop) 
-       return 0; 
-     if (value > alpha) { 
-       if (value >= beta) 
-         return value; 
-       alpha = value; 
-     } 
-   } 
- /* 
-  ************************************************************ 
-  *                                                          * 
-  *  All moves have been searched.  If none were legal, it   * 
-  *  must be a mate since we have to be in check to reach    * 
-  *  QuiesceEvasions().                                      * 
-  *                                                          * 
-  ************************************************************ 
-  */ 
-   if (moves_searched == 0) { 
-     value = -(MATE - ply); 
-     if (value >= alpha && value < beta) { 
-       SavePV(tree, ply, 0); 
- #if defined(TRACE) 
-       if (ply <= trace_level) 
-         printf("Search() no moves!  ply=%d\n",-  ply );
 
- #endif 
-     } 
-     return value; 
-   } else if (alpha != original_alpha) { 
-     tree->pv[ply - 1] = tree->pv[ply]; 
-     tree->pv[ply - 1].path[ply - 1] = tree->curmv[ply - 1]; 
-   } 
-   return alpha; 
- } 
-