Rev 108 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 33 | pmbaty | 1 | #include "chess.h" | 
| 2 | #include "data.h" | ||
| 154 | pmbaty | 3 | #if defined(SYZYGY) | 
| 4 | #  include "tbprobe.h" | ||
| 5 | #endif | ||
| 6 | /* last modified 08/03/16 */ | ||
| 33 | pmbaty | 7 | /* | 
| 8 |  ******************************************************************************* | ||
| 9 |  *                                                                             * | ||
| 10 |  *   Search() is the recursive routine used to implement the alpha/beta        * | ||
| 11 |  *   negamax search (similar to minimax but simpler to code.)  Search() is     * | ||
| 12 |  *   called whenever there is "depth" remaining so that all moves are subject  * | ||
| 13 |  *   to searching.  Search() recursively calls itself so long as there is at   * | ||
| 14 |  *   least one ply of depth left, otherwise it calls Quiesce() instead.        * | ||
| 15 |  *                                                                             * | ||
| 16 |  ******************************************************************************* | ||
| 17 |  */ | ||
| 108 | pmbaty | 18 | int Search(TREE * RESTRICT tree, int ply, int depth, int wtm, int alpha, | 
| 19 | int beta, int in_check, int do_null) { | ||
| 20 | int repeat = 0, value = 0, pv_node = alpha != beta - 1, n_depth; | ||
| 21 | int searched[256]; | ||
| 33 | pmbaty | 22 | |
| 23 | /* | ||
| 24 |  ************************************************************ | ||
| 25 |  *                                                          * | ||
| 108 | pmbaty | 26 |  *  Timeout.  Check to see if we have searched enough nodes * | 
| 33 | pmbaty | 27 |  *  that it is time to peek at how much time has been used, * | 
| 28 |  *  or if is time to check for operator keyboard input.     * | ||
| 29 |  *  This is usually enough nodes to force a time/input      * | ||
| 30 |  *  check about once per second, except when the target     * | ||
| 31 |  *  time per move is very small, in which case we try to    * | ||
| 32 |  *  check the time more frequently.                         * | ||
| 33 |  *                                                          * | ||
| 34 |  *  Note that we check input or time-out in thread 0.  This * | ||
| 35 |  *  makes the code simpler and eliminates some problematic  * | ||
| 36 |  *  race conditions.                                        * | ||
| 37 |  *                                                          * | ||
| 38 |  ************************************************************ | ||
| 39 |  */ | ||
| 40 | #if defined(NODES) | ||
| 108 | pmbaty | 41 | if (search_nodes && --temp_search_nodes <= 0) { | 
| 33 | pmbaty | 42 | abort_search = 1; | 
| 43 | return 0; | ||
| 44 |   } | ||
| 45 | #endif | ||
| 46 | if (tree->thread_id == 0) { | ||
| 47 | if (--next_time_check <= 0) { | ||
| 48 | next_time_check = nodes_between_time_checks; | ||
| 49 | if (TimeCheck(tree, 1)) { | ||
| 50 | abort_search = 1; | ||
| 51 | return 0; | ||
| 52 |       } | ||
| 53 | if (CheckInput()) { | ||
| 54 | Interrupt(ply); | ||
| 55 | if (abort_search) | ||
| 56 | return 0; | ||
| 57 |       } | ||
| 58 |     } | ||
| 59 |   } | ||
| 60 | if (ply >= MAXPLY - 1) | ||
| 61 | return beta; | ||
| 62 | /* | ||
| 63 |  ************************************************************ | ||
| 64 |  *                                                          * | ||
| 108 | pmbaty | 65 |  *  Draws.  Check for draw by repetition, which includes    * | 
| 33 | pmbaty | 66 |  *  50 move draws also.  This is the quickest way to get    * | 
| 67 |  *  out of further searching, with minimal effort.  This    * | ||
| 108 | pmbaty | 68 |  *  and the next four steps are skipped for moves at the    * | 
| 33 | pmbaty | 69 |  *  root (ply = 1).                                         * | 
| 70 |  *                                                          * | ||
| 71 |  ************************************************************ | ||
| 72 |  */ | ||
| 73 | if (ply > 1) { | ||
| 74 | if ((repeat = Repeat(tree, ply))) { | ||
| 154 | pmbaty | 75 | if (repeat == 2 || !in_check) { | 
| 108 | pmbaty | 76 | value = DrawScore(wtm); | 
| 77 | if (value < beta) | ||
| 154 | pmbaty | 78 | SavePV(tree, ply, repeat); | 
| 33 | pmbaty | 79 | #if defined(TRACE) | 
| 108 | pmbaty | 80 | if (ply <= trace_level) | 
| 154 | pmbaty | 81 | printf("draw by %s detected, ply=%d.\n", | 
| 82 | (repeat == 3) ? "50-move" : "repetition", ply); | ||
| 33 | pmbaty | 83 | #endif | 
| 108 | pmbaty | 84 | return value; | 
| 85 |       } | ||
| 33 | pmbaty | 86 |     } | 
| 87 | /* | ||
| 88 |  ************************************************************ | ||
| 89 |  *                                                          * | ||
| 108 | pmbaty | 90 |  *  Mate distance pruning.  If we have found a mate, we can * | 
| 91 |  *  stop if we are too deep to find a shorter mate.  This   * | ||
| 92 |  *  only affects the size of the tree in positions where    * | ||
| 93 |  *  there are forced mates.  It does not change the outcome * | ||
| 94 |  *  of the search at all, just the time it takes.           * | ||
| 95 |  *                                                          * | ||
| 96 |  ************************************************************ | ||
| 97 |  */ | ||
| 98 | alpha = Max(alpha, -MATE + ply - 1); | ||
| 99 | beta = Min(beta, MATE - ply); | ||
| 100 | if (alpha >= beta) | ||
| 101 | return alpha; | ||
| 102 | /* | ||
| 103 |  ************************************************************ | ||
| 104 |  *                                                          * | ||
| 105 |  *  Trans/Ref.  Check the transposition/refutation (hash)   * | ||
| 33 | pmbaty | 106 |  *  table to see if we have searched this position          * | 
| 107 |  *  previously and still have the results available.  We    * | ||
| 108 |  *  might get a real score, or a bound, or perhaps only a   * | ||
| 109 |  *  good move to try first.  The possible results are:      * | ||
| 110 |  *                                                          * | ||
| 108 | pmbaty | 111 |  *  1. HashProbe() returns "HASH_HIT".  This terminates the * | 
| 112 |  *  search instantly and we simply return the value found   * | ||
| 113 |  *  in the hash table.  This value is simply the value we   * | ||
| 114 |  *  found when we did a real search in this position        * | ||
| 115 |  *  previously, and ProbeTransRef() verifies that the value * | ||
| 116 |  *  is useful based on draft and current bounds.            * | ||
| 33 | pmbaty | 117 |  *                                                          * | 
| 118 |  *  2. HashProbe() returns "AVOID_NULL_MOVE" which means    * | ||
| 119 |  *  the hashed score/bound was no good, but it indicated    * | ||
| 120 |  *  that trying a null-move in this position would be a     * | ||
| 121 |  *  waste of time since it will likely fail low, not high.  * | ||
| 122 |  *                                                          * | ||
| 108 | pmbaty | 123 |  *  3. HashProbe() returns "HASH_MISS" when forces us to do * | 
| 124 |  *  a normal search to resolve this node.                   * | ||
| 33 | pmbaty | 125 |  *                                                          * | 
| 126 |  ************************************************************ | ||
| 127 |  */ | ||
| 108 | pmbaty | 128 | switch (HashProbe(tree, ply, depth, wtm, alpha, beta, &value)) { | 
| 33 | pmbaty | 129 | case HASH_HIT: | 
| 130 | return value; | ||
| 131 | case AVOID_NULL_MOVE: | ||
| 132 | do_null = 0; | ||
| 133 | case HASH_MISS: | ||
| 134 | break; | ||
| 135 |     } | ||
| 136 | /* | ||
| 137 |  ************************************************************ | ||
| 138 |  *                                                          * | ||
| 108 | pmbaty | 139 |  *  EGTBs.  Now it's time to try a probe into the endgame   * | 
| 33 | pmbaty | 140 |  *  tablebase files.  This is done if we notice that there  * | 
| 154 | pmbaty | 141 |  *  are 6 or fewer pieces left on the board AND the 50 move * | 
| 142 |  *  counter is zero which enables probing the WDL EGTBs     * | ||
| 143 |  *  correctly.  Probing after a capture won't work as it is * | ||
| 144 |  *  possible that there is a necessary pawn push here and   * | ||
| 145 |  *  there to reset the 50 move counter, otherwise we could  * | ||
| 146 |  *  think we were following a winning path but heading to a * | ||
| 147 |  *  draw.                                                   * | ||
| 148 |  *                                                          * | ||
| 33 | pmbaty | 149 |  *  This is another way to get out of the search quickly,   * | 
| 150 |  *  but not as quickly as the previous steps since this can * | ||
| 151 |  *  result in an I/O operation.                             * | ||
| 152 |  *                                                          * | ||
| 153 |  *  Note that in "swindle mode" this can be turned off by   * | ||
| 154 |  *  Iterate() setting "EGTB_use = 0" so that we won't probe * | ||
| 155 |  *  the EGTBs since we are searching only the root moves    * | ||
| 156 |  *  that lead to a draw and we want to play the move that   * | ||
| 157 |  *  makes the draw more difficult to reach by the opponent  * | ||
| 158 |  *  to give him a chance to make a mistake.                 * | ||
| 159 |  *                                                          * | ||
| 160 |  *  Another special case is that we slightly fudge the      * | ||
| 154 | pmbaty | 161 |  *  score for draws.  The scores are -0.03 for a "blessed   * | 
| 162 |  *  loss", 0.0 for a pure draw, and +0.03 for a "cursed     * | ||
| 163 |  *  win".  These are then modified by adding 0.01 if the    * | ||
| 164 |  *  side on move is ahead in material, and subtracting 0.01 * | ||
| 165 |  *  if the side on move is behind material.  This creates   * | ||
| 166 |  *  the following inequality:                               * | ||
| 33 | pmbaty | 167 |  *                                                          * | 
| 154 | pmbaty | 168 |  *     BL- < BL= < BL+ < D- < D= < D+ < CW- < CW= <CW+      * | 
| 169 |  *                                                          * | ||
| 170 |  *  Where BL=blessed loss, D = draw, and CW = cursed win,   * | ||
| 171 |  *  and - means behind in material, = means equal material, * | ||
| 172 |  *  and + means ahead in material.                          * | ||
| 173 |  *                                                          * | ||
| 33 | pmbaty | 174 |  ************************************************************ | 
| 175 |  */ | ||
| 154 | pmbaty | 176 | #if defined(SYZYGY) | 
| 108 | pmbaty | 177 | if (depth > EGTB_depth && TotalAllPieces <= EGTB_use && | 
| 154 | pmbaty | 178 | !Castle(ply, white) && !Castle(ply, black) && Reversible(ply) == 0) { | 
| 179 | int tb_result; | ||
| 33 | pmbaty | 180 | |
| 181 | tree->egtb_probes++; | ||
| 154 | pmbaty | 182 |       tb_result = | 
| 183 | tb_probe_wdl(Occupied(white), Occupied(black), | ||
| 184 | Kings(white) | Kings(black), Queens(white) | Queens(black), | ||
| 185 | Rooks(white) | Rooks(black), Bishops(white) | Bishops(black), | ||
| 186 | Knights(white) | Knights(black), Pawns(white) | Pawns(black), | ||
| 187 | Reversible(ply), 0, EnPassant(ply), wtm, HashKey); | ||
| 188 | if (tb_result != TB_RESULT_FAILED) { | ||
| 108 | pmbaty | 189 | tree->egtb_hits++; | 
| 154 | pmbaty | 190 | switch (tb_result) { | 
| 191 | case TB_LOSS: | ||
| 192 | alpha = -TBWIN; | ||
| 193 | break; | ||
| 194 | case TB_BLESSED_LOSS: | ||
| 195 | alpha = -3; | ||
| 196 | break; | ||
| 197 | case TB_DRAW: | ||
| 198 | alpha = 0; | ||
| 199 | break; | ||
| 200 | case TB_CURSED_WIN: | ||
| 201 | alpha = 3; | ||
| 202 | break; | ||
| 203 | case TB_WIN: | ||
| 204 | alpha = TBWIN; | ||
| 205 | break; | ||
| 206 |         } | ||
| 207 | if (tb_result != TB_LOSS && tb_result != TB_WIN) { | ||
| 108 | pmbaty | 208 | if (MaterialSTM(wtm) > 0) | 
| 209 | alpha += 1; | ||
| 210 | else if (MaterialSTM(wtm) < 0) | ||
| 211 | alpha -= 1; | ||
| 33 | pmbaty | 212 |         } | 
| 213 | if (alpha < beta) | ||
| 154 | pmbaty | 214 | SavePV(tree, ply, 4); | 
| 33 | pmbaty | 215 | return alpha; | 
| 216 |       } | ||
| 217 |     } | ||
| 218 | #endif | ||
| 219 | /* | ||
| 220 |  ************************************************************ | ||
| 221 |  *                                                          * | ||
| 108 | pmbaty | 222 |  *  Null-move.  We now know there is no quick way to get    * | 
| 223 |  *  out of here, which leaves one more possibility,         * | ||
| 224 |  *  although it does require a search, but to a reduced     * | ||
| 225 |  *  depth.  We try a null move to see if we can get a quick * | ||
| 226 |  *  cutoff with only a little work.  This operates as       * | ||
| 227 |  *  follows.  Instead of making a legal move, the side on   * | ||
| 228 |  *  move passes and does nothing.  The resulting position   * | ||
| 229 |  *  is searched to a shallower depth than normal (see       * | ||
| 230 |  *  below).  This will result in a cutoff if our position   * | ||
| 231 |  *  is very good, but it produces the cutoff much quicker   * | ||
| 232 |  *  since the search is far shallower than a normal search  * | ||
| 233 |  *  that would also be likely to fail high.                 * | ||
| 33 | pmbaty | 234 |  *                                                          * | 
| 108 | pmbaty | 235 |  *  The reduction amount starts off at null_depth (normally * | 
| 236 |  *  set to 3 but the user can change this via the crafty    * | ||
| 237 |  *  personality command) but is then increased as follows:  * | ||
| 238 |  *                                                          * | ||
| 239 |  *     R = null_depth + depth / null_divisor                * | ||
| 240 |  *                                                          * | ||
| 241 |  *  null_divisor defaults to 6, but this can also be set    * | ||
| 242 |  *  by the user to try more/less aggressive settings.       * | ||
| 243 |  *                                                          * | ||
| 33 | pmbaty | 244 |  *  This is skipped for any of the following reasons:       * | 
| 245 |  *                                                          * | ||
| 108 | pmbaty | 246 |  *  1. The side on move is in check.  The null move         * | 
| 247 |  *     results in an illegal position.                      * | ||
| 248 |  *  2. No more than one null move can appear in succession  * | ||
| 249 |  *     as all this does is burn 2x plies of depth.          * | ||
| 250 |  *  3. The side on move has only pawns left, which makes    * | ||
| 251 |  *     zugzwang positions more likely.                      * | ||
| 252 |  *  4. The transposition table probe found an entry that    * | ||
| 253 |  *     indicates that a null-move search will not fail      * | ||
| 254 |  *     high, so we avoid the wasted effort.                 * | ||
| 33 | pmbaty | 255 |  *                                                          * | 
| 256 |  ************************************************************ | ||
| 257 |  */ | ||
| 108 | pmbaty | 258 | |
| 33 | pmbaty | 259 | tree->last[ply] = tree->last[ply - 1]; | 
| 108 | pmbaty | 260 | n_depth = (TotalPieces(wtm, occupied) > 9 || n_root_moves > 17 || | 
| 154 | pmbaty | 261 | depth > 3) ? 1 : 3; | 
| 108 | pmbaty | 262 | if (do_null && !pv_node && depth > n_depth && !in_check && | 
| 263 | TotalPieces(wtm, occupied)) { | ||
| 33 | pmbaty | 264 | uint64_t save_hash_key; | 
| 108 | pmbaty | 265 | int R = null_depth + depth / null_divisor; | 
| 33 | pmbaty | 266 | |
| 267 | tree->curmv[ply] = 0; | ||
| 268 | #if defined(TRACE) | ||
| 269 | if (ply <= trace_level) | ||
| 108 | pmbaty | 270 | Trace(tree, ply, depth, wtm, value - 1, value, "SearchNull", serial, | 
| 271 | NULL_MOVE, 0); | ||
| 33 | pmbaty | 272 | #endif | 
| 273 | tree->status[ply + 1] = tree->status[ply]; | ||
| 274 | Reversible(ply + 1) = 0; | ||
| 275 | save_hash_key = HashKey; | ||
| 276 | if (EnPassant(ply + 1)) { | ||
| 277 | HashEP(EnPassant(ply + 1)); | ||
| 278 | EnPassant(ply + 1) = 0; | ||
| 279 |       } | ||
| 108 | pmbaty | 280 | tree->null_done[Min(R, 15)]++; | 
| 281 | if (depth - R - 1 > 0) | ||
| 33 | pmbaty | 282 |         value = | 
| 108 | pmbaty | 283 | -Search(tree, ply + 1, depth - R - 1, Flip(wtm), -beta, -beta + 1, | 
| 284 | 0, NO_NULL); | ||
| 33 | pmbaty | 285 |       else | 
| 108 | pmbaty | 286 | value = -Quiesce(tree, ply + 1, Flip(wtm), -beta, -beta + 1, 1); | 
| 33 | pmbaty | 287 | HashKey = save_hash_key; | 
| 288 | if (abort_search || tree->stop) | ||
| 289 | return 0; | ||
| 290 | if (value >= beta) { | ||
| 108 | pmbaty | 291 | HashStore(tree, ply, depth, wtm, LOWER, value, tree->hash_move[ply]); | 
| 33 | pmbaty | 292 | return value; | 
| 293 |       } | ||
| 294 |     } | ||
| 295 | /* | ||
| 296 |  ************************************************************ | ||
| 297 |  *                                                          * | ||
| 108 | pmbaty | 298 |  *  IID.  This step is rarely executed.  It is used when    * | 
| 33 | pmbaty | 299 |  *  there is no best move from the hash table, and this is  * | 
| 300 |  *  a PV node, since we need a good move to search first.   * | ||
| 301 |  *  While killers moves are good, they are not quite good   * | ||
| 302 |  *  enough.  the simplest solution is to try a shallow      * | ||
| 303 |  *  search (depth-2) to get a move.  note that when we call * | ||
| 304 |  *  Search() with depth-2, it, too, will not have a hash    * | ||
| 305 |  *  move, and will therefore recursively continue this      * | ||
| 306 |  *  process, hence the name "internal iterative deepening." * | ||
| 307 |  *                                                          * | ||
| 308 |  ************************************************************ | ||
| 309 |  */ | ||
| 108 | pmbaty | 310 | tree->next_status[ply].phase = HASH; | 
| 311 | if (!tree->hash_move[ply] && depth >= 6 && do_null && ply > 1 && pv_node) { | ||
| 312 | tree->curmv[ply] = 0; | ||
| 313 | if (depth - 2 > 0) | ||
| 314 |         value = | ||
| 315 | Search(tree, ply, depth - 2, wtm, alpha, beta, in_check, DO_NULL); | ||
| 316 |       else | ||
| 317 | value = Quiesce(tree, ply, wtm, alpha, beta, 1); | ||
| 318 | if (abort_search || tree->stop) | ||
| 319 | return 0; | ||
| 320 | if (value > alpha) { | ||
| 321 | if (value < beta) { | ||
| 322 | if ((int) tree->pv[ply - 1].pathl > ply) | ||
| 323 | tree->hash_move[ply] = tree->pv[ply - 1].path[ply]; | ||
| 324 | } else | ||
| 325 | tree->hash_move[ply] = tree->curmv[ply]; | ||
| 326 | tree->last[ply] = tree->last[ply - 1]; | ||
| 327 | tree->next_status[ply].phase = HASH; | ||
| 33 | pmbaty | 328 |       } | 
| 329 |     } | ||
| 330 |   } | ||
| 108 | pmbaty | 331 | /* | 
| 33 | pmbaty | 332 |  ************************************************************ | 
| 333 |  *                                                          * | ||
| 108 | pmbaty | 334 |  *  Search moves.  Now we call SearchMoveList() to interate * | 
| 335 |  *  through the move list and search each new position.     * | ||
| 336 |  *  Note that this is done in a separate procedure because  * | ||
| 337 |  *  this is also the code that is used to do the parallel   * | ||
| 338 |  *  search.                                                 * | ||
| 339 |  *                                                          * | ||
| 340 |  ************************************************************ | ||
| 341 |  */ | ||
| 342 | searched[0] = 0; | ||
| 343 |   value = | ||
| 344 | SearchMoveList(tree, ply, depth, wtm, alpha, beta, searched, in_check, | ||
| 345 | repeat, serial); | ||
| 346 | return value; | ||
| 347 | } | ||
| 348 | |||
| 154 | pmbaty | 349 | /* last modified 08/03/16 */ | 
| 108 | pmbaty | 350 | /* | 
| 351 |  ******************************************************************************* | ||
| 352 |  *                                                                             * | ||
| 353 |  *   SearchMoveList() is the recursive routine used to implement the main      * | ||
| 354 |  *   search loop.  This code is responsible for iterating through the move     * | ||
| 355 |  *   list until it encounters a condition that ends the search at this ply.    * | ||
| 356 |  *   At that point it simply returns the current negamax value to the caller   * | ||
| 357 |  *   to handle as necessary.                                                   * | ||
| 358 |  *                                                                             * | ||
| 359 |  *   The "mode" flag indicates which of the following conditions apply here    * | ||
| 360 |  *   which directly controls parts of the search.                              * | ||
| 361 |  *                                                                             * | ||
| 362 |  *      mode = serial   ->  this is a serial search.                           * | ||
| 363 |  *                                                                             * | ||
| 364 |  *      mode = parallel ->  this is a parallel search, which implies that this * | ||
| 365 |  *                          is a partial search which means we do NOT want to  * | ||
| 366 |  *                          do any trans/ref updating and we also need to take * | ||
| 367 |  *                          care about locking things that are being updated   * | ||
| 368 |  *                          by more than one thread in parallel.               * | ||
| 369 |  *                                                                             * | ||
| 370 |  *   When mode = parallel, this code performs the same function as the old     * | ||
| 371 |  *   SearchParallel() code, except that it is the main search loop for the     * | ||
| 372 |  *   program, there is no longer any duplicated code.  This is called by the   * | ||
| 373 |  *   normal Search() function and by ThreadWait() where idle processes wait    * | ||
| 374 |  *   for work and then call this procedure to search a subset of the moves at  * | ||
| 375 |  *   this ply (in parallel with other threads).                                * | ||
| 376 |  *                                                                             * | ||
| 377 |  ******************************************************************************* | ||
| 378 |  */ | ||
| 379 | int SearchMoveList(TREE * RESTRICT tree, int ply, int depth, int wtm, | ||
| 380 | int alpha, int beta, int searched[], int in_check, int repeat, int mode) { | ||
| 381 | TREE *current; | ||
| 382 | int extend, reduce, check, original_alpha = alpha, t_beta; | ||
| 154 | pmbaty | 383 | int i, j, value = 0, pv_node = alpha != beta - 1, search_result, order; | 
| 384 | int moves_done = 0, bestmove, type; | ||
| 108 | pmbaty | 385 | |
| 386 | /* | ||
| 387 |  ************************************************************ | ||
| 388 |  *                                                          * | ||
| 389 |  *  Basic initialization before we begin the loop through   * | ||
| 390 |  *  the move list.  If this is a parallel search, we have   * | ||
| 391 |  *  already searched one move, so we set t_beta to alpha+1  * | ||
| 392 |  *  to set up for a normal PVS search (for moves 2-n)       * | ||
| 393 |  *  instead of using alpha,beta for the first move as we do * | ||
| 394 |  *  in a normal search.  Also, if this is a serial search,  * | ||
| 395 |  *  we are fixing to search the first move so we set the    * | ||
| 396 |  *  searched move counter to zero, where in a parallel      * | ||
| 397 |  *  search this has already been done and we leave it alone * | ||
| 398 |  *  here.                                                   * | ||
| 399 |  *                                                          * | ||
| 400 |  *  We also set <current> to tree for a serial search, and  * | ||
| 401 |  *  to tree->parent for a parallel search since we need to  * | ||
| 402 |  *  share the move list at split nodes.                     * | ||
| 403 |  *                                                          * | ||
| 404 |  ************************************************************ | ||
| 405 |  */ | ||
| 406 | tree->next_status[ply].phase = HASH; | ||
| 407 | if (mode == parallel) { | ||
| 408 | current = tree->parent; | ||
| 409 | t_beta = alpha + 1; | ||
| 410 | } else { | ||
| 411 | current = tree; | ||
| 412 | t_beta = beta; | ||
| 413 |   } | ||
| 414 | /* | ||
| 415 |  ************************************************************ | ||
| 416 |  *                                                          * | ||
| 417 |  *  Iterate.  Now iterate through the move list and search  * | ||
| 33 | pmbaty | 418 |  *  the resulting positions.  Note that Search() culls any  * | 
| 419 |  *  move that is not legal by using Check().  The special   * | ||
| 420 |  *  case is that we must find one legal move to search to   * | ||
| 421 |  *  confirm that it's not a mate or draw.                   * | ||
| 422 |  *                                                          * | ||
| 108 | pmbaty | 423 |  *  We call NextMove() which will generate moves in the     * | 
| 424 |  *  normal way (captures, killers, etc) or it will use the  * | ||
| 425 |  *  GenerateEvasions() generator if we are in check.  For   * | ||
| 426 |  *  the special case of ply=1, we use NextRootMove() since  * | ||
| 427 |  *  the ply=1 move list has been generated and the order is * | ||
| 428 |  *  updated as each search iteration is executed.           * | ||
| 33 | pmbaty | 429 |  *                                                          * | 
| 430 |  ************************************************************ | ||
| 431 |  */ | ||
| 432 | while (1) { | ||
| 108 | pmbaty | 433 | if (ply == 1 && moves_done == 1 && alpha == original_alpha && | 
| 434 | mode == serial) | ||
| 33 | pmbaty | 435 | break; | 
| 108 | pmbaty | 436 | if (mode == parallel) | 
| 437 | Lock(current->lock); | ||
| 154 | pmbaty | 438 | order = (ply > 1) ? NextMove(current, ply, depth, wtm, in_check) | 
| 439 | : NextRootMove(current, tree, wtm); | ||
| 108 | pmbaty | 440 | if (mode == parallel) { | 
| 154 | pmbaty | 441 | tree->curmv[ply] = current->curmv[ply]; | 
| 108 | pmbaty | 442 | Unlock(current->lock); | 
| 443 |     } | ||
| 444 | if (!order) | ||
| 33 | pmbaty | 445 | break; | 
| 446 | #if defined(TRACE) | ||
| 447 | if (ply <= trace_level) | ||
| 154 | pmbaty | 448 | Trace(tree, ply, depth, wtm, alpha, beta, "SearchMoveList", mode, | 
| 449 | current->phase[ply], order); | ||
| 33 | pmbaty | 450 | #endif | 
| 108 | pmbaty | 451 | MakeMove(tree, ply, wtm, tree->curmv[ply]); | 
| 33 | pmbaty | 452 | tree->nodes_searched++; | 
| 154 | pmbaty | 453 | search_result = ILLEGAL; | 
| 108 | pmbaty | 454 | if (in_check || !Check(wtm)) | 
| 33 | pmbaty | 455 | do { | 
| 108 | pmbaty | 456 | searched[0]++; | 
| 457 |         moves_done++; | ||
| 154 | pmbaty | 458 | search_result = LEGAL; | 
| 108 | pmbaty | 459 | searched[searched[0]] = tree->curmv[ply]; | 
| 33 | pmbaty | 460 | /* | 
| 461 |  ************************************************************ | ||
| 462 |  *                                                          * | ||
| 108 | pmbaty | 463 |  *  Check.  If the move to be made checks the opponent,     * | 
| 33 | pmbaty | 464 |  *  then we need to remember that he's in check and also    * | 
| 108 | pmbaty | 465 |  *  extend the depth by one ply for him to get out.         * | 
| 33 | pmbaty | 466 |  *                                                          * | 
| 467 |  *  We do not extend unsafe checking moves (as indicated by * | ||
| 108 | pmbaty | 468 |  *  the SEE algorithm), since these are usually a waste of  * | 
| 469 |  *  time and simply blow up the tree search space.          * | ||
| 33 | pmbaty | 470 |  *                                                          * | 
| 108 | pmbaty | 471 |  *  Note that extending here disables any potential foward  * | 
| 472 |  *  pruning or reductions for this move.                    * | ||
| 473 |  *                                                          * | ||
| 33 | pmbaty | 474 |  ************************************************************ | 
| 475 |  */ | ||
| 476 | extend = 0; | ||
| 477 | reduce = 0; | ||
| 108 | pmbaty | 478 | if (Check(Flip(wtm))) { | 
| 479 | check = 1; | ||
| 480 | if (SEEO(tree, wtm, | ||
| 481 | tree->curmv[ply]) - pcval[Captured(tree->curmv[ply])] <= | ||
| 482 | 0) { | ||
| 33 | pmbaty | 483 | extend = check_depth; | 
| 484 | tree->extensions_done++; | ||
| 485 |           } | ||
| 486 | } else | ||
| 108 | pmbaty | 487 | check = 0; | 
| 33 | pmbaty | 488 | /* | 
| 489 |  ************************************************************ | ||
| 490 |  *                                                          * | ||
| 108 | pmbaty | 491 |  *  Futility.  First attempt at forward pruning based on    * | 
| 492 |  *  the futility idea.                                      * | ||
| 33 | pmbaty | 493 |  *                                                          * | 
| 494 |  *  We have an array of pruning margin values that are      * | ||
| 495 |  *  indexed by depth (remaining plies left until we drop    * | ||
| 496 |  *  into the quiescence search) and which increase with     * | ||
| 497 |  *  depth since more depth means a greater chance of        * | ||
| 498 |  *  bringing the score back up to alpha or beyond.  If the  * | ||
| 499 |  *  current material + the bonus is less than alpha, we     * | ||
| 500 |  *  simply avoid searching this move at all, and skip to    * | ||
| 501 |  *  the next move without expending any more effort.  Note  * | ||
| 502 |  *  that this is classic forward-pruning and can certainly  * | ||
| 503 |  *  introduce errors into the search.  However, cluster     * | ||
| 504 |  *  testing has shown that this improves play in real       * | ||
| 505 |  *  games.  The current implementation only prunes in the   * | ||
| 108 | pmbaty | 506 |  *  last 6 plies before quiescence, although this can be    * | 
| 33 | pmbaty | 507 |  *  tuned with the "eval" command changing the "pruning     * | 
| 108 | pmbaty | 508 |  *  depth" value to something other than 7 (test is for     * | 
| 509 |  *  depth < pruning depth, current value is 7 which prunes  * | ||
| 510 |  *  in last 6 plies only).  Testing shows no benefit in     * | ||
| 511 |  *  larger values than 7, although this might change in     * | ||
| 33 | pmbaty | 512 |  *  future versions as other things are modified.           * | 
| 513 |  *                                                          * | ||
| 514 |  *  Exception:                                              * | ||
| 515 |  *                                                          * | ||
| 516 |  *    We do not prune if we are safely pushing a passed     * | ||
| 517 |  *    pawn to the 6th rank, where it becomes very dangerous * | ||
| 518 |  *    since it can promote in two more moves.               * | ||
| 519 |  *                                                          * | ||
| 108 | pmbaty | 520 |  *  All pruning and reduction code is skipped if any of the * | 
| 521 |  *  following are true:                                     * | ||
| 522 |  *                                                          * | ||
| 523 |  *  (1) side on move is in check.                           * | ||
| 524 |  *                                                          * | ||
| 525 |  *  (2) move has not already been flagged for a search      * | ||
| 526 |  *      extension.                                          * | ||
| 527 |  *                                                          * | ||
| 528 |  *  (3) this is not the first move at this ply.             * | ||
| 529 |  *                                                          * | ||
| 33 | pmbaty | 530 |  ************************************************************ | 
| 531 |  */ | ||
| 154 | pmbaty | 532 | if (!in_check && (!extend || !pv_node) && order > 1 && | 
| 108 | pmbaty | 533 | !(PawnPush(wtm, tree->curmv[ply]))) { | 
| 154 | pmbaty | 534 | if (depth < FP_depth && !check && | 
| 535 | MaterialSTM(wtm) + FP_margin[depth] <= alpha && !pv_node) { | ||
| 108 | pmbaty | 536 | tree->moves_fpruned++; | 
| 537 | break; | ||
| 33 | pmbaty | 538 |           } | 
| 539 | /* | ||
| 540 |  ************************************************************ | ||
| 541 |  *                                                          * | ||
| 108 | pmbaty | 542 |  *  LMP.  Final attempt at forward pruning based on the     * | 
| 543 |  *  "late move pruning" idea (a take-off on LMR).           * | ||
| 33 | pmbaty | 544 |  *                                                          * | 
| 108 | pmbaty | 545 |  *  The basic idea here is that once we have searched a     * | 
| 546 |  *  significant number of moves at a ply, it becomes less   * | ||
| 547 |  *  and less likely that any of the moves left will produce * | ||
| 548 |  *  a cutoff.  If the move appears to be simple (not a      * | ||
| 549 |  *  check, etc) then we simply skip it, once the move count * | ||
| 550 |  *  has been satisfied.  At present, we only do this in the * | ||
| 154 | pmbaty | 551 |  *  last 16 plies although this might be changed in the     * | 
| 552 |  *  future.  If you look at the LMP array after it has been * | ||
| 553 |  *  initialized, you will notice that it is unlikely that   * | ||
| 554 |  *  LMP can be triggered much beyond depth 8 as you have to * | ||
| 555 |  *  have a BUNCH of moves to search to reach those limits.  * | ||
| 33 | pmbaty | 556 |  *                                                          * | 
| 108 | pmbaty | 557 |  ************************************************************ | 
| 558 |  */ | ||
| 154 | pmbaty | 559 | if (order > LMP[depth] && depth < LMP_depth && !pv_node && !check && | 
| 560 | alpha > -MATE + 300 && !CaptureOrPromote(tree->curmv[ply])) { | ||
| 108 | pmbaty | 561 | tree->moves_mpruned++; | 
| 562 | break; | ||
| 563 |           } | ||
| 564 | /* | ||
| 565 |  ************************************************************ | ||
| 33 | pmbaty | 566 |  *                                                          * | 
| 108 | pmbaty | 567 |  *  LMR.  Now it's time to try to reduce the search depth   * | 
| 568 |  *  if the move appears to be "poor" because it appears     * | ||
| 569 |  *  later in the move list.                                 * | ||
| 33 | pmbaty | 570 |  *                                                          * | 
| 108 | pmbaty | 571 |  *  The reduction is variable and is done via a table look- * | 
| 572 |  *  up that uses a function based on remaining depth (more  * | ||
| 573 |  *  depth remaining, the larger the reduction) and the      * | ||
| 574 |  *  number of moves searched (more moves searched, the      * | ||
| 575 |  *  larger the reduction).  The "shape" of this reduction   * | ||
| 576 |  *  formula is user-settable via the "lmr" command.         * | ||
| 577 |  *                                                          * | ||
| 33 | pmbaty | 578 |  ************************************************************ | 
| 579 |  */ | ||
| 108 | pmbaty | 580 | reduce = LMR[Min(depth, 31)][Min(order, 63)]; | 
| 154 | pmbaty | 581 | if (reduce && (pv_node || extend)) | 
| 582 |             reduce--; | ||
| 108 | pmbaty | 583 | tree->LMR_done[reduce]++; | 
| 33 | pmbaty | 584 |         } | 
| 108 | pmbaty | 585 | /* | 
| 33 | pmbaty | 586 |  ************************************************************ | 
| 587 |  *                                                          * | ||
| 108 | pmbaty | 588 |  *  Now do the PVS search on the current move.              * | 
| 33 | pmbaty | 589 |  *                                                          * | 
| 108 | pmbaty | 590 |  *  Note that we do the usual alpha/beta cutoff tests here  * | 
| 591 |  *  but we only set an indicator that is used after we have * | ||
| 592 |  *  called Unmake().  This cleaned up the exit from search  * | ||
| 593 |  *  and makes it easier to understand when there is only    * | ||
| 594 |  *  one point where this is done, without needing multiple  * | ||
| 595 |  *  Unmake() calls when there are different exit points.    * | ||
| 33 | pmbaty | 596 |  *                                                          * | 
| 154 | pmbaty | 597 |  ************************************************************** | 
| 33 | pmbaty | 598 |  */ | 
| 108 | pmbaty | 599 |         value = | 
| 600 | SearchMove(tree, ply, depth, wtm, alpha, t_beta, beta, extend, | ||
| 601 | reduce, check); | ||
| 602 | if (value > alpha) { | ||
| 154 | pmbaty | 603 | search_result = IN_WINDOW; | 
| 108 | pmbaty | 604 | if (value >= beta) | 
| 154 | pmbaty | 605 | search_result = FAIL_HIGH; | 
| 108 | pmbaty | 606 | if (mode == parallel && ply == 1) | 
| 154 | pmbaty | 607 | search_result = FAIL_HIGH; | 
| 108 | pmbaty | 608 |         } | 
| 609 | } while (0); | ||
| 610 | UnmakeMove(tree, ply, wtm, tree->curmv[ply]); | ||
| 611 | if (abort_search || tree->stop) | ||
| 612 | break; | ||
| 33 | pmbaty | 613 | /* | 
| 614 |  ************************************************************ | ||
| 615 |  *                                                          * | ||
| 108 | pmbaty | 616 |  *  Test 1.  When we get here, we have made a move,         * | 
| 617 |  *  searched it (and re-searched if necessary/appropriate), * | ||
| 618 |  *  and the move has been unmade so that the board is in a  * | ||
| 619 |  *  correct state.                                          * | ||
| 33 | pmbaty | 620 |  *                                                          * | 
| 154 | pmbaty | 621 |  *  If search_result = FAIL_HIGH, the search failed high.   * | 
| 622 |  *  The first thing to handle is the case where we are at   * | ||
| 108 | pmbaty | 623 |  *  ply=1, which is a special case.  If we are going to     * | 
| 624 |  *  fail high here and terminate the search immediately, we * | ||
| 625 |  *  need to build the fail-high PV to back up to Iterate()  * | ||
| 626 |  *  so it will produce the correct output and widen the     * | ||
| 627 |  *  alpha/beta window.                                      * | ||
| 33 | pmbaty | 628 |  *                                                          * | 
| 108 | pmbaty | 629 |  *  We then check to see if this is a parallel search.  If  * | 
| 630 |  *  so then we are done here, but we need to tell all of    * | ||
| 631 |  *  the siblings that are helping at this split point that  * | ||
| 632 |  *  they should immediately stop searching here since we    * | ||
| 633 |  *  don't need their results.                               * | ||
| 33 | pmbaty | 634 |  *                                                          * | 
| 108 | pmbaty | 635 |  *  Otherwise we update the killer moves and history        * | 
| 636 |  *  counters and store the fail-high information in the     * | ||
| 637 |  *  trans/ref table for future use if we happen to reach    * | ||
| 638 |  *  this position again.                                    * | ||
| 33 | pmbaty | 639 |  *                                                          * | 
| 640 |  ************************************************************ | ||
| 641 |  */ | ||
| 154 | pmbaty | 642 | if (search_result == FAIL_HIGH) { | 
| 108 | pmbaty | 643 | if (ply == 1) { | 
| 644 | if (!tree->stop) { | ||
| 645 | tree->pv[1].path[1] = tree->curmv[1]; | ||
| 646 | tree->pv[1].pathl = 2; | ||
| 647 | tree->pv[1].pathh = 0; | ||
| 648 | tree->pv[1].pathd = iteration; | ||
| 649 | tree->pv[0] = tree->pv[1]; | ||
| 33 | pmbaty | 650 |         } | 
| 108 | pmbaty | 651 |       } | 
| 652 | #if (CPUS > 1) | ||
| 653 | if (mode == parallel) { | ||
| 654 | Lock(lock_smp); | ||
| 655 | Lock(tree->parent->lock); | ||
| 656 | if (!tree->stop) { | ||
| 657 | int proc; | ||
| 658 | |||
| 659 |           parallel_aborts++; | ||
| 154 | pmbaty | 660 | for (proc = 0; proc < smp_max_threads; proc++) | 
| 108 | pmbaty | 661 | if (tree->parent->siblings[proc] && proc != tree->thread_id) | 
| 662 | ThreadStop(tree->parent->siblings[proc]); | ||
| 663 |         } | ||
| 664 | Unlock(tree->parent->lock); | ||
| 665 | Unlock(lock_smp); | ||
| 154 | pmbaty | 666 | return beta; | 
| 108 | pmbaty | 667 |       } | 
| 668 | #endif | ||
| 669 | tree->fail_highs++; | ||
| 670 | if (order == 1) | ||
| 671 | tree->fail_high_first_move++; | ||
| 672 | HashStore(tree, ply, depth, wtm, LOWER, value, tree->curmv[ply]); | ||
| 673 | History(tree, ply, depth, wtm, tree->curmv[ply], searched); | ||
| 674 | return beta; | ||
| 675 | /* | ||
| 33 | pmbaty | 676 |  ************************************************************ | 
| 677 |  *                                                          * | ||
| 154 | pmbaty | 678 |  *  Test 2.  If search_result = IN_WINDOW, this is a search * | 
| 679 |  *  that improved alpha without failing high.  We simply    * | ||
| 680 |  *  update alpha and continue searching moves.              * | ||
| 33 | pmbaty | 681 |  *                                                          * | 
| 108 | pmbaty | 682 |  *  Special case:  If ply = 1 in a normal search, we have   * | 
| 683 |  *  a best move and score that just changed.  We need to    * | ||
| 684 |  *  update the root move list by adding the PV and the      * | ||
| 685 |  *  score, and then we look to make sure this new "best     * | ||
| 686 |  *  move" is not actually worse than the best we have found * | ||
| 687 |  *  so far this iteration.  If it is worse, we restore the  * | ||
| 688 |  *  best move and score from the real best move so our      * | ||
| 689 |  *  search window won't be out of whack, which would let    * | ||
| 690 |  *  moves with scores in between this bad move and the best * | ||
| 154 | pmbaty | 691 |  *  move fail high, cause re-searches, and waste time.  We  * | 
| 692 |  *  also need to restore the root move list so that the     * | ||
| 693 |  *  best move (the one we just used to replace the move     * | ||
| 694 |  *  with a worse score) is first so it is searched first on * | ||
| 695 |  *  the next iteration.                                     * | ||
| 33 | pmbaty | 696 |  *                                                          * | 
| 108 | pmbaty | 697 |  *  If this is ply = 1, we display the PV to keep the user  * | 
| 698 |  *  informed.                                               * | ||
| 699 |  *                                                          * | ||
| 33 | pmbaty | 700 |  ************************************************************ | 
| 701 |  */ | ||
| 154 | pmbaty | 702 | } else if (search_result == IN_WINDOW) { | 
| 108 | pmbaty | 703 | alpha = value; | 
| 704 | if (ply == 1 && mode == serial) { | ||
| 154 | pmbaty | 705 | int best; | 
| 706 | |||
| 707 |        // | ||
| 708 |        // update path/score for this move | ||
| 709 |        // | ||
| 108 | pmbaty | 710 | tree->pv[1].pathv = value; | 
| 711 | tree->pv[0] = tree->pv[1]; | ||
| 154 | pmbaty | 712 | for (best = 0; best < n_root_moves; best++) | 
| 713 | if (root_moves[best].move == tree->pv[1].path[1]) { | ||
| 714 | root_moves[best].path = tree->pv[1]; | ||
| 715 | root_moves[best].path.pathv = alpha; | ||
| 716 | break; | ||
| 33 | pmbaty | 717 |           } | 
| 154 | pmbaty | 718 |        // | 
| 719 |        // if this move is not #1 in root list, move it there | ||
| 720 |        // | ||
| 721 | if (best != 0) { | ||
| 722 |           ROOT_MOVE t; | ||
| 723 | t = root_moves[best]; | ||
| 724 | for (i = best; i > 0; i--) | ||
| 725 | root_moves[i] = root_moves[i - 1]; | ||
| 726 | root_moves[0] = t; | ||
| 727 |         } | ||
| 728 |        // | ||
| 729 |        // if a better score has already been found then move that | ||
| 730 |        // move to the front of the list and update alpha bound. | ||
| 731 |        // | ||
| 732 | for (i = 0; i < n_root_moves; i++) { | ||
| 733 | if (value <= root_moves[i].path.pathv) { | ||
| 734 |             ROOT_MOVE t; | ||
| 108 | pmbaty | 735 | value = root_moves[i].path.pathv; | 
| 736 | alpha = value; | ||
| 737 | tree->pv[0] = root_moves[i].path; | ||
| 738 | tree->pv[1] = tree->pv[0]; | ||
| 154 | pmbaty | 739 | t = root_moves[i]; | 
| 740 | for (j = i; j > 0; j--) | ||
| 741 | root_moves[j] = root_moves[j - 1]; | ||
| 742 | root_moves[0] = t; | ||
| 33 | pmbaty | 743 |           } | 
| 154 | pmbaty | 744 |         } | 
| 108 | pmbaty | 745 | Output(tree); | 
| 746 | failhi_delta = 16; | ||
| 747 | faillo_delta = 16; | ||
| 748 |       } | ||
| 749 |     } | ||
| 33 | pmbaty | 750 | /* | 
| 751 |  ************************************************************ | ||
| 752 |  *                                                          * | ||
| 154 | pmbaty | 753 |  *  Test 3.  If search_result = ILLEGAL, this search was    * | 
| 754 |  *  given an illegal move and no search was done, we skip   * | ||
| 755 |  *  any updating and simply select the next move to search. * | ||
| 108 | pmbaty | 756 |  *                                                          * | 
| 757 |  ************************************************************ | ||
| 758 |  */ | ||
| 154 | pmbaty | 759 | else if (search_result == ILLEGAL) | 
| 108 | pmbaty | 760 | continue; | 
| 761 | t_beta = alpha + 1; | ||
| 762 | /* | ||
| 763 |  ************************************************************ | ||
| 764 |  *                                                          * | ||
| 765 |  *  SMP.  If are doing an SMP search, and we have idle      * | ||
| 33 | pmbaty | 766 |  *  processors, now is the time to get them involved.  We   * | 
| 767 |  *  have now satisfied the "young brothers wait" condition  * | ||
| 108 | pmbaty | 768 |  *  since we have searched at least one move.  All that is  * | 
| 769 |  *  left is to check the split constraints to see if this   * | ||
| 770 |  *  is an acceptable split point.                           * | ||
| 33 | pmbaty | 771 |  *                                                          * | 
| 772 |  *    (1) We can't split within N plies of the frontier     * | ||
| 773 |  *        nodes to avoid excessive split overhead.          * | ||
| 774 |  *                                                          * | ||
| 108 | pmbaty | 775 |  *    (2) We can't split until at least N nodes have been   * | 
| 33 | pmbaty | 776 |  *        searched since this thread was last split, to     * | 
| 777 |  *        avoid splitting too often, mainly in endgames.    * | ||
| 778 |  *                                                          * | ||
| 779 |  *    (3) We have to have searched one legal move to avoid  * | ||
| 780 |  *        splitting at a node where we have no legal moves  * | ||
| 781 |  *        (the first move tried might have been illegal as  * | ||
| 782 |  *        in when we encounter a stalemate).                * | ||
| 783 |  *                                                          * | ||
| 784 |  *    (4) If we are at ply=1, we can't split unless the     * | ||
| 785 |  *        smp_split_at_root flag is set to 1, AND the next  * | ||
| 786 |  *        move in the ply=1 move list is not flagged as     * | ||
| 787 |  *        "do not search in parallel" which happens when    * | ||
| 788 |  *        this move was a best move in the last couple of   * | ||
| 789 |  *        searches and we want all processors on it at once * | ||
| 790 |  *        to get a score back quicker.                      * | ||
| 791 |  *                                                          * | ||
| 108 | pmbaty | 792 |  *    (5) if the variable smp_split is != 0, we have idle   * | 
| 793 |  *        threads that can help, which means we want to get * | ||
| 794 |  *        them involved quickly, OR if this node is an      * | ||
| 795 |  *        acceptable "gratuitous-split" point by being far  * | ||
| 796 |  *        enough from the tips of the tree to avoid         * | ||
| 797 |  *        excessive overhead.                               * | ||
| 33 | pmbaty | 798 |  *                                                          * | 
| 108 | pmbaty | 799 |  *  We use this code recursively to perform a parallel      * | 
| 800 |  *  search at this ply.  But when we finish a partial piece * | ||
| 801 |  *  of the search in parallel, we don't need to update any  * | ||
| 802 |  *  search data structures, we will defer that until all of * | ||
| 803 |  *  parallel threads complete and return back into this     * | ||
| 804 |  *  code after the parallel search has been collapsed back  * | ||
| 805 |  *  to one instance of search at this ply.                  * | ||
| 33 | pmbaty | 806 |  *                                                          * | 
| 807 |  *  Special case:  we do not split if we are at ply=1 and   * | ||
| 808 |  *  alpha == original_alpha.  That means the first move     * | ||
| 809 |  *  failed low, and we are going to exit search and return  * | ||
| 810 |  *  to Iterate() to report this.                            * | ||
| 811 |  *                                                          * | ||
| 108 | pmbaty | 812 |  *  In Generation II, multiple threads can reach this point * | 
| 813 |  *  at the same time.  We allow multiple threads to split   * | ||
| 814 |  *  at the same time, but then the idle threads will choose * | ||
| 815 |  *  to join the thread with the most attractive split point * | ||
| 816 |  *  rather than just taking pot-luck.  The only limitation  * | ||
| 817 |  *  on a thread adding a split point here is that if the    * | ||
| 154 | pmbaty | 818 |  *  thread already has enough joinable split points that    * | 
| 819 |  *  have not been joined yet, we do not incur the overhead  * | ||
| 820 |  *  of creating another split point until one of the        * | ||
| 821 |  *  existing split points has been completed or a thread    * | ||
| 822 |  *  joins at at one of those available split points.        * | ||
| 33 | pmbaty | 823 |  *                                                          * | 
| 108 | pmbaty | 824 |  *  We do not lock anything here, as the split operation    * | 
| 825 |  *  only affects thread-local data.  When the split is done * | ||
| 826 |  *  then the ThreadJoin() function will acquire the lock    * | ||
| 827 |  *  needed to avoid race conditions during the join op-     * | ||
| 828 |  *  eration.                                                * | ||
| 33 | pmbaty | 829 |  *                                                          * | 
| 830 |  ************************************************************ | ||
| 831 |  */ | ||
| 832 | #if (CPUS > 1) | ||
| 108 | pmbaty | 833 | if (mode == serial && moves_done && smp_threads && | 
| 834 | ThreadSplit(tree, ply, depth, alpha, original_alpha, moves_done)) | ||
| 33 | pmbaty | 835 | do { | 
| 836 | tree->alpha = alpha; | ||
| 837 | tree->beta = beta; | ||
| 838 | tree->value = alpha; | ||
| 108 | pmbaty | 839 | tree->wtm = wtm; | 
| 33 | pmbaty | 840 | tree->ply = ply; | 
| 841 | tree->depth = depth; | ||
| 108 | pmbaty | 842 | tree->in_check = in_check; | 
| 843 | tree->searched = searched; | ||
| 844 | if (Split(tree)) { | ||
| 33 | pmbaty | 845 | if (abort_search || tree->stop) | 
| 846 | return 0; | ||
| 847 | value = tree->value; | ||
| 848 | if (value > alpha) { | ||
| 108 | pmbaty | 849 | if (ply == 1) | 
| 850 | tree->pv[0] = tree->pv[1]; | ||
| 33 | pmbaty | 851 | if (value >= beta) { | 
| 108 | pmbaty | 852 | HashStore(tree, ply, depth, wtm, LOWER, value, tree->cutmove); | 
| 33 | pmbaty | 853 | return value; | 
| 854 |             } | ||
| 855 | alpha = value; | ||
| 856 | break; | ||
| 857 |           } | ||
| 858 |         } | ||
| 859 | } while (0); | ||
| 860 | #endif | ||
| 861 |   } | ||
| 862 | /* | ||
| 863 |  ************************************************************ | ||
| 864 |  *                                                          * | ||
| 108 | pmbaty | 865 |  *  SMP Cleanup.  If we are doing an SMP search, there are  * | 
| 866 |  *  no "end-of-search" things to do.  We have searched all  * | ||
| 867 |  *  the remaining moves at this ply in parallel, and now    * | ||
| 868 |  *  return and let the original search that started this    * | ||
| 869 |  *  sub-tree clean up, do the tests for mate/stalemate,     * | ||
| 870 |  *  update the hash table, etc.                             * | ||
| 33 | pmbaty | 871 |  *                                                          * | 
| 108 | pmbaty | 872 |  *  As we return, we end back up in Thread() where we       * | 
| 873 |  *  started, which then copies the best score/etc back to   * | ||
| 874 |  *  the parent thread.                                      * | ||
| 875 |  *                                                          * | ||
| 33 | pmbaty | 876 |  ************************************************************ | 
| 877 |  */ | ||
| 108 | pmbaty | 878 | if (abort_search || tree->stop || mode == parallel) | 
| 879 | return alpha; | ||
| 880 | /* | ||
| 881 |  ************************************************************ | ||
| 882 |  *                                                          * | ||
| 883 |  *  Search completed.  All moves have been searched.  If    * | ||
| 884 |  *  none were legal, return either MATE or DRAW depending   * | ||
| 885 |  *  on whether the side to move is in check or not.         * | ||
| 886 |  *                                                          * | ||
| 887 |  ************************************************************ | ||
| 888 |  */ | ||
| 889 | if (moves_done == 0) { | ||
| 890 | value = (Check(wtm)) ? -(MATE - ply) : DrawScore(wtm); | ||
| 33 | pmbaty | 891 | if (value >= alpha && value < beta) { | 
| 892 | SavePV(tree, ply, 0); | ||
| 893 | #if defined(TRACE) | ||
| 894 | if (ply <= trace_level) | ||
| 895 | printf("Search() no moves! ply=%d\n", ply); | ||
| 896 | #endif | ||
| 897 |     } | ||
| 898 | return value; | ||
| 899 | } else { | ||
| 900 |     bestmove = | ||
| 108 | pmbaty | 901 | (alpha == | 
| 902 | original_alpha) ? tree->hash_move[ply] : tree->pv[ply].path[ply]; | ||
| 33 | pmbaty | 903 | type = (alpha == original_alpha) ? UPPER : EXACT; | 
| 904 | if (repeat == 2 && alpha != -(MATE - ply - 1)) { | ||
| 108 | pmbaty | 905 | value = DrawScore(wtm); | 
| 33 | pmbaty | 906 | if (value < beta) | 
| 154 | pmbaty | 907 | SavePV(tree, ply, 3); | 
| 33 | pmbaty | 908 | #if defined(TRACE) | 
| 909 | if (ply <= trace_level) | ||
| 910 | printf("draw by 50 move rule detected, ply=%d.\n", ply); | ||
| 911 | #endif | ||
| 912 | return value; | ||
| 913 | } else if (alpha != original_alpha) { | ||
| 914 | tree->pv[ply - 1] = tree->pv[ply]; | ||
| 915 | tree->pv[ply - 1].path[ply - 1] = tree->curmv[ply - 1]; | ||
| 916 |     } | ||
| 108 | pmbaty | 917 | HashStore(tree, ply, depth, wtm, type, alpha, bestmove); | 
| 33 | pmbaty | 918 | return alpha; | 
| 919 |   } | ||
| 920 | } | ||
| 921 | |||
| 154 | pmbaty | 922 | /* last modified 08/03/16 */ | 
| 33 | pmbaty | 923 | /* | 
| 924 |  ******************************************************************************* | ||
| 925 |  *                                                                             * | ||
| 108 | pmbaty | 926 |  *   SearchMove() implements the PVS search and returns the value.  We do a    * | 
| 927 |  *   null-window search with the window (alpha, t_beta) and if that fails high * | ||
| 928 |  *   we repeat the search with the window {alpha, beta} assuming that beta !=  * | ||
| 929 |  *   t_beta.                                                                   * | ||
| 33 | pmbaty | 930 |  *                                                                             * | 
| 931 |  ******************************************************************************* | ||
| 932 |  */ | ||
| 108 | pmbaty | 933 | int SearchMove(TREE * RESTRICT tree, int ply, int depth, int wtm, int alpha, | 
| 934 | int t_beta, int beta, int extend, int reduce, int check) { | ||
| 935 | int value; | ||
| 33 | pmbaty | 936 | /* | 
| 937 |  ************************************************************ | ||
| 938 |  *                                                          * | ||
| 108 | pmbaty | 939 |  *  PVS search.  We have determined whether the depth is to * | 
| 33 | pmbaty | 940 |  *  be changed by an extension or a reduction.  If we get   * | 
| 941 |  *  to this point, then the move is not being pruned.  So   * | ||
| 942 |  *  off we go to a recursive search/quiescence call to work * | ||
| 943 |  *  our way toward a terminal node.                         * | ||
| 944 |  *                                                          * | ||
| 108 | pmbaty | 945 |  *  There is one special-case to handle.  If the depth was  * | 
| 33 | pmbaty | 946 |  *  reduced, and Search() returns a value >= beta then      * | 
| 947 |  *  accepting that is risky (we reduced the move as we      * | ||
| 948 |  *  thought it was bad and expected it to fail low) so we   * | ||
| 949 |  *  repeat the search using the original (non-reduced)      * | ||
| 950 |  *  depth to see if the fail-high happens again.            * | ||
| 951 |  *                                                          * | ||
| 952 |  ************************************************************ | ||
| 953 |  */ | ||
| 108 | pmbaty | 954 | if (depth + extend - reduce - 1 > 0) { | 
| 955 |     value = | ||
| 956 | -Search(tree, ply + 1, depth + extend - reduce - 1, Flip(wtm), | ||
| 957 | -t_beta, -alpha, check, DO_NULL); | ||
| 958 | if (value > alpha && reduce) { | ||
| 959 |       value = | ||
| 960 | -Search(tree, ply + 1, depth - 1, Flip(wtm), -t_beta, -alpha, check, | ||
| 961 | DO_NULL); | ||
| 962 |     } | ||
| 963 | } else | ||
| 964 | value = -Quiesce(tree, ply + 1, Flip(wtm), -t_beta, -alpha, 1); | ||
| 965 | if (abort_search || tree->stop) | ||
| 966 | return 0; | ||
| 33 | pmbaty | 967 | /* | 
| 968 |  ************************************************************ | ||
| 969 |  *                                                          * | ||
| 108 | pmbaty | 970 |  *  PVS re-search.  This is the PVS re-search code.  If we  * | 
| 971 |  *  reach this point and value > alpha and value < beta,    * | ||
| 972 |  *  then this can not be a null-window search.  We have to  * | ||
| 973 |  *  re-search the position with the original beta value     * | ||
| 974 |  *  to see if it still fails high before we treat this as a * | ||
| 975 |  *  real fail-high and back up the value to the previous    * | ||
| 976 |  *  ply.                                                    * | ||
| 33 | pmbaty | 977 |  *                                                          * | 
| 978 |  ************************************************************ | ||
| 979 |  */ | ||
| 108 | pmbaty | 980 | if (value > alpha && value < beta && t_beta < beta) { | 
| 981 | if (ply == 1) | ||
| 982 | return beta; | ||
| 983 | if (depth + extend - 1 > 0) | ||
| 984 |       value = | ||
| 985 | -Search(tree, ply + 1, depth + extend - 1, Flip(wtm), -beta, -alpha, | ||
| 986 | check, DO_NULL); | ||
| 987 |     else | ||
| 988 | value = -Quiesce(tree, ply + 1, Flip(wtm), -beta, -alpha, 1); | ||
| 33 | pmbaty | 989 | if (abort_search || tree->stop) | 
| 108 | pmbaty | 990 | return 0; | 
| 33 | pmbaty | 991 |   } | 
| 108 | pmbaty | 992 | return value; | 
| 33 | pmbaty | 993 | } |