Rev 169 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 96 | pmbaty | 1 | /* |
| 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 |
||
| 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) |
||
| 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
||
| 185 | pmbaty | 5 | Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad |
| 96 | pmbaty | 6 | |
| 7 | Stockfish is free software: you can redistribute it and/or modify |
||
| 8 | it under the terms of the GNU General Public License as published by |
||
| 9 | the Free Software Foundation, either version 3 of the License, or |
||
| 10 | (at your option) any later version. |
||
| 11 | |||
| 12 | Stockfish is distributed in the hope that it will be useful, |
||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 15 | GNU General Public License for more details. |
||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License |
||
| 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
| 19 | */ |
||
| 20 | |||
| 21 | #include <cassert> |
||
| 22 | |||
| 23 | #include "movepick.h" |
||
| 24 | |||
| 25 | namespace { |
||
| 26 | |||
| 27 | enum Stages { |
||
| 185 | pmbaty | 28 | MAIN_TT, CAPTURE_INIT, GOOD_CAPTURE, REFUTATION, QUIET_INIT, QUIET, BAD_CAPTURE, |
| 29 | EVASION_TT, EVASION_INIT, EVASION, |
||
| 30 | PROBCUT_TT, PROBCUT_INIT, PROBCUT, |
||
| 31 | QSEARCH_TT, QCAPTURE_INIT, QCAPTURE, QCHECK_INIT, QCHECK |
||
| 96 | pmbaty | 32 | }; |
| 33 | |||
| 185 | pmbaty | 34 | // Helper filter used with select() |
| 35 | const auto Any = [](){ return true; }; |
||
| 36 | |||
| 169 | pmbaty | 37 | // partial_insertion_sort() sorts moves in descending order up to and including |
| 38 | // a given limit. The order of moves smaller than the limit is left unspecified. |
||
| 39 | void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit) { |
||
| 96 | pmbaty | 40 | |
| 169 | pmbaty | 41 | for (ExtMove *sortedEnd = begin, *p = begin + 1; p < end; ++p) |
| 42 | if (p->value >= limit) |
||
| 43 | { |
||
| 44 | ExtMove tmp = *p, *q; |
||
| 45 | *p = *++sortedEnd; |
||
| 46 | for (q = sortedEnd; q != begin && *(q - 1) < tmp; --q) |
||
| 47 | *q = *(q - 1); |
||
| 48 | *q = tmp; |
||
| 49 | } |
||
| 96 | pmbaty | 50 | } |
| 51 | |||
| 52 | } // namespace |
||
| 53 | |||
| 54 | |||
| 55 | /// Constructors of the MovePicker class. As arguments we pass information |
||
| 56 | /// to help it to return the (presumably) good moves first, to decide which |
||
| 57 | /// moves to return (in the quiescence search, for instance, we only want to |
||
| 58 | /// search captures, promotions, and some checks) and how important good move |
||
| 59 | /// ordering is at the current node. |
||
| 60 | |||
| 169 | pmbaty | 61 | /// MovePicker constructor for the main search |
| 62 | MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, |
||
| 185 | pmbaty | 63 | const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm, Move* killers) |
| 64 | : pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), |
||
| 65 | refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d) { |
||
| 96 | pmbaty | 66 | |
| 67 | assert(d > DEPTH_ZERO); |
||
| 68 | |||
| 185 | pmbaty | 69 | stage = pos.checkers() ? EVASION_TT : MAIN_TT; |
| 96 | pmbaty | 70 | ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE; |
| 154 | pmbaty | 71 | stage += (ttMove == MOVE_NONE); |
| 96 | pmbaty | 72 | } |
| 73 | |||
| 169 | pmbaty | 74 | /// MovePicker constructor for quiescence search |
| 185 | pmbaty | 75 | MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, |
| 76 | const CapturePieceToHistory* cph, const PieceToHistory** ch, Square rs) |
||
| 77 | : pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), recaptureSquare(rs), depth(d) { |
||
| 96 | pmbaty | 78 | |
| 79 | assert(d <= DEPTH_ZERO); |
||
| 80 | |||
| 185 | pmbaty | 81 | stage = pos.checkers() ? EVASION_TT : QSEARCH_TT; |
| 82 | ttMove = ttm |
||
| 83 | && pos.pseudo_legal(ttm) |
||
| 84 | && (depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare) ? ttm : MOVE_NONE; |
||
| 154 | pmbaty | 85 | stage += (ttMove == MOVE_NONE); |
| 96 | pmbaty | 86 | } |
| 87 | |||
| 185 | pmbaty | 88 | /// MovePicker constructor for ProbCut: we generate captures with SEE greater |
| 169 | pmbaty | 89 | /// than or equal to the given threshold. |
| 90 | MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePieceToHistory* cph) |
||
| 91 | : pos(p), captureHistory(cph), threshold(th) { |
||
| 96 | pmbaty | 92 | |
| 93 | assert(!pos.checkers()); |
||
| 94 | |||
| 185 | pmbaty | 95 | stage = PROBCUT_TT; |
| 96 | pmbaty | 96 | ttMove = ttm |
| 97 | && pos.pseudo_legal(ttm) |
||
| 98 | && pos.capture(ttm) |
||
| 169 | pmbaty | 99 | && pos.see_ge(ttm, threshold) ? ttm : MOVE_NONE; |
| 154 | pmbaty | 100 | stage += (ttMove == MOVE_NONE); |
| 96 | pmbaty | 101 | } |
| 102 | |||
| 185 | pmbaty | 103 | /// MovePicker::score() assigns a numerical value to each move in a list, used |
| 104 | /// for sorting. Captures are ordered by Most Valuable Victim (MVV), preferring |
||
| 105 | /// captures with a good history. Quiets moves are ordered using the histories. |
||
| 169 | pmbaty | 106 | template<GenType Type> |
| 107 | void MovePicker::score() { |
||
| 96 | pmbaty | 108 | |
| 169 | pmbaty | 109 | static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type"); |
| 96 | pmbaty | 110 | |
| 111 | for (auto& m : *this) |
||
| 169 | pmbaty | 112 | if (Type == CAPTURES) |
| 113 | m.value = PieceValue[MG][pos.piece_on(to_sq(m))] |
||
| 185 | pmbaty | 114 | + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))] / 8; |
| 96 | pmbaty | 115 | |
| 169 | pmbaty | 116 | else if (Type == QUIETS) |
| 117 | m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] |
||
| 185 | pmbaty | 118 | + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] |
| 119 | + (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)] |
||
| 120 | + (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]; |
||
| 96 | pmbaty | 121 | |
| 169 | pmbaty | 122 | else // Type == EVASIONS |
| 123 | { |
||
| 124 | if (pos.capture(m)) |
||
| 125 | m.value = PieceValue[MG][pos.piece_on(to_sq(m))] |
||
| 126 | - Value(type_of(pos.moved_piece(m))); |
||
| 127 | else |
||
| 185 | pmbaty | 128 | m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] |
| 129 | + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] |
||
| 130 | - (1 << 28); |
||
| 169 | pmbaty | 131 | } |
| 96 | pmbaty | 132 | } |
| 133 | |||
| 185 | pmbaty | 134 | /// MovePicker::select() returns the next move satisfying a predicate function. |
| 135 | /// It never returns the TT move. |
||
| 136 | template<MovePicker::PickType T, typename Pred> |
||
| 137 | Move MovePicker::select(Pred filter) { |
||
| 96 | pmbaty | 138 | |
| 185 | pmbaty | 139 | while (cur < endMoves) |
| 140 | { |
||
| 141 | if (T == Best) |
||
| 142 | std::swap(*cur, *std::max_element(cur, endMoves)); |
||
| 143 | |||
| 144 | move = *cur++; |
||
| 145 | |||
| 146 | if (move != ttMove && filter()) |
||
| 147 | return move; |
||
| 148 | } |
||
| 149 | return move = MOVE_NONE; |
||
| 150 | } |
||
| 151 | |||
| 152 | /// MovePicker::next_move() is the most important method of the MovePicker class. It |
||
| 153 | /// returns a new pseudo legal move every time it is called until there are no more |
||
| 154 | /// moves left, picking the move with the highest score from a list of generated moves. |
||
| 169 | pmbaty | 155 | Move MovePicker::next_move(bool skipQuiets) { |
| 96 | pmbaty | 156 | |
| 185 | pmbaty | 157 | top: |
| 154 | pmbaty | 158 | switch (stage) { |
| 96 | pmbaty | 159 | |
| 185 | pmbaty | 160 | case MAIN_TT: |
| 161 | case EVASION_TT: |
||
| 162 | case QSEARCH_TT: |
||
| 163 | case PROBCUT_TT: |
||
| 154 | pmbaty | 164 | ++stage; |
| 165 | return ttMove; |
||
| 96 | pmbaty | 166 | |
| 185 | pmbaty | 167 | case CAPTURE_INIT: |
| 168 | case PROBCUT_INIT: |
||
| 169 | case QCAPTURE_INIT: |
||
| 170 | cur = endBadCaptures = moves; |
||
| 154 | pmbaty | 171 | endMoves = generate<CAPTURES>(pos, cur); |
| 185 | pmbaty | 172 | |
| 154 | pmbaty | 173 | score<CAPTURES>(); |
| 174 | ++stage; |
||
| 185 | pmbaty | 175 | goto top; |
| 96 | pmbaty | 176 | |
| 185 | pmbaty | 177 | case GOOD_CAPTURE: |
| 178 | if (select<Best>([&](){ |
||
| 179 | return pos.see_ge(move, Value(-55 * (cur-1)->value / 1024)) ? |
||
| 180 | // Move losing capture to endBadCaptures to be tried later |
||
| 181 | true : (*endBadCaptures++ = move, false); })) |
||
| 182 | return move; |
||
| 96 | pmbaty | 183 | |
| 185 | pmbaty | 184 | // Prepare the pointers to loop over the refutations array |
| 185 | cur = std::begin(refutations); |
||
| 186 | endMoves = std::end(refutations); |
||
| 96 | pmbaty | 187 | |
| 185 | pmbaty | 188 | // If the countermove is the same as a killer, skip it |
| 189 | if ( refutations[0].move == refutations[2].move |
||
| 190 | || refutations[1].move == refutations[2].move) |
||
| 191 | --endMoves; |
||
| 192 | |||
| 154 | pmbaty | 193 | ++stage; |
| 169 | pmbaty | 194 | /* fallthrough */ |
| 96 | pmbaty | 195 | |
| 185 | pmbaty | 196 | case REFUTATION: |
| 197 | if (select<Next>([&](){ return move != MOVE_NONE |
||
| 198 | && !pos.capture(move) |
||
| 199 | && pos.pseudo_legal(move); })) |
||
| 154 | pmbaty | 200 | return move; |
| 201 | ++stage; |
||
| 169 | pmbaty | 202 | /* fallthrough */ |
| 154 | pmbaty | 203 | |
| 204 | case QUIET_INIT: |
||
| 205 | cur = endBadCaptures; |
||
| 206 | endMoves = generate<QUIETS>(pos, cur); |
||
| 185 | pmbaty | 207 | |
| 154 | pmbaty | 208 | score<QUIETS>(); |
| 169 | pmbaty | 209 | partial_insertion_sort(cur, endMoves, -4000 * depth / ONE_PLY); |
| 154 | pmbaty | 210 | ++stage; |
| 169 | pmbaty | 211 | /* fallthrough */ |
| 154 | pmbaty | 212 | |
| 213 | case QUIET: |
||
| 185 | pmbaty | 214 | if ( !skipQuiets |
| 215 | && select<Next>([&](){return move != refutations[0] |
||
| 216 | && move != refutations[1] |
||
| 217 | && move != refutations[2];})) |
||
| 218 | return move; |
||
| 169 | pmbaty | 219 | |
| 185 | pmbaty | 220 | // Prepare the pointers to loop over the bad captures |
| 221 | cur = moves; |
||
| 222 | endMoves = endBadCaptures; |
||
| 223 | |||
| 154 | pmbaty | 224 | ++stage; |
| 169 | pmbaty | 225 | /* fallthrough */ |
| 96 | pmbaty | 226 | |
| 185 | pmbaty | 227 | case BAD_CAPTURE: |
| 228 | return select<Next>(Any); |
||
| 96 | pmbaty | 229 | |
| 185 | pmbaty | 230 | case EVASION_INIT: |
| 154 | pmbaty | 231 | cur = moves; |
| 232 | endMoves = generate<EVASIONS>(pos, cur); |
||
| 185 | pmbaty | 233 | |
| 154 | pmbaty | 234 | score<EVASIONS>(); |
| 235 | ++stage; |
||
| 169 | pmbaty | 236 | /* fallthrough */ |
| 154 | pmbaty | 237 | |
| 185 | pmbaty | 238 | case EVASION: |
| 239 | return select<Best>(Any); |
||
| 96 | pmbaty | 240 | |
| 185 | pmbaty | 241 | case PROBCUT: |
| 242 | return select<Best>([&](){ return pos.see_ge(move, threshold); }); |
||
| 96 | pmbaty | 243 | |
| 185 | pmbaty | 244 | case QCAPTURE: |
| 245 | if (select<Best>([&](){ return depth > DEPTH_QS_RECAPTURES |
||
| 246 | || to_sq(move) == recaptureSquare; })) |
||
| 247 | return move; |
||
| 96 | pmbaty | 248 | |
| 185 | pmbaty | 249 | // If we did not find any move and we do not try checks, we have finished |
| 250 | if (depth != DEPTH_QS_CHECKS) |
||
| 251 | return MOVE_NONE; |
||
| 252 | |||
| 154 | pmbaty | 253 | ++stage; |
| 169 | pmbaty | 254 | /* fallthrough */ |
| 154 | pmbaty | 255 | |
| 185 | pmbaty | 256 | case QCHECK_INIT: |
| 154 | pmbaty | 257 | cur = moves; |
| 258 | endMoves = generate<QUIET_CHECKS>(pos, cur); |
||
| 96 | pmbaty | 259 | |
| 154 | pmbaty | 260 | ++stage; |
| 169 | pmbaty | 261 | /* fallthrough */ |
| 154 | pmbaty | 262 | |
| 185 | pmbaty | 263 | case QCHECK: |
| 264 | return select<Next>(Any); |
||
| 96 | pmbaty | 265 | } |
| 154 | pmbaty | 266 | |
| 185 | pmbaty | 267 | assert(false); |
| 268 | return MOVE_NONE; // Silence warning |
||
| 96 | pmbaty | 269 | } |