]> git.sesse.net Git - stockfish/blob - src/movepick.cpp
Split non capture in two sets when ordering
[stockfish] / src / movepick.cpp
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-2010 Marco Costalba, Joona Kiiski, Tord Romstad
5
6   Stockfish is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
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 "movegen.h"
24 #include "movepick.h"
25 #include "search.h"
26 #include "types.h"
27
28 namespace {
29
30   enum MovegenPhase {
31     PH_TT_MOVE,       // Transposition table move
32     PH_GOOD_CAPTURES, // Queen promotions and captures with SEE values >= captureThreshold (captureThreshold <= 0)
33     PH_GOOD_PROBCUT,  // Queen promotions and captures with SEE values > captureThreshold (captureThreshold >= 0)
34     PH_KILLERS,       // Killer moves from the current ply
35     PH_NONCAPTURES_1, // Non-captures and underpromotions with positive score
36     PH_NONCAPTURES_2, // Non-captures and underpromotions with non-positive score
37     PH_BAD_CAPTURES,  // Queen promotions and captures with SEE values < captureThreshold (captureThreshold <= 0)
38     PH_EVASIONS,      // Check evasions
39     PH_QCAPTURES,     // Captures in quiescence search
40     PH_QCHECKS,       // Non-capture checks in quiescence search
41     PH_STOP
42   };
43
44   CACHE_LINE_ALIGNMENT
45   const uint8_t MainSearchTable[] = { PH_TT_MOVE, PH_GOOD_CAPTURES, PH_KILLERS, PH_NONCAPTURES_1, PH_NONCAPTURES_2, PH_BAD_CAPTURES, PH_STOP };
46   const uint8_t EvasionTable[] = { PH_TT_MOVE, PH_EVASIONS, PH_STOP };
47   const uint8_t QsearchWithChecksTable[] = { PH_TT_MOVE, PH_QCAPTURES, PH_QCHECKS, PH_STOP };
48   const uint8_t QsearchWithoutChecksTable[] = { PH_TT_MOVE, PH_QCAPTURES, PH_STOP };
49   const uint8_t ProbCutTable[] = { PH_TT_MOVE, PH_GOOD_PROBCUT, PH_STOP };
50 }
51
52 /// Constructors for the MovePicker class. As arguments we pass information
53 /// to help it to return the presumably good moves first, to decide which
54 /// moves to return (in the quiescence search, for instance, we only want to
55 /// search captures, promotions and some checks) and about how important good
56 /// move ordering is at the current node.
57
58 MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h,
59                        SearchStack* ss, Value beta) : pos(p), H(h) {
60   captureThreshold = 0;
61   badCaptures = moves + MAX_MOVES;
62
63   assert(d > DEPTH_ZERO);
64
65   if (p.in_check())
66   {
67       killers[0].move = killers[1].move = MOVE_NONE;
68       phasePtr = EvasionTable;
69   }
70   else
71   {
72       killers[0].move = ss->killers[0];
73       killers[1].move = ss->killers[1];
74
75       // Consider sligtly negative captures as good if at low
76       // depth and far from beta.
77       if (ss && ss->eval < beta - PawnValueMidgame && d < 3 * ONE_PLY)
78           captureThreshold = -PawnValueMidgame;
79
80       phasePtr = MainSearchTable;
81   }
82
83   ttMove = (ttm && pos.move_is_pl(ttm) ? ttm : MOVE_NONE);
84   phasePtr += int(ttMove == MOVE_NONE) - 1;
85   go_next_phase();
86 }
87
88 MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const History& h)
89                       : pos(p), H(h) {
90
91   assert(d <= DEPTH_ZERO);
92
93   if (p.in_check())
94       phasePtr = EvasionTable;
95   else if (d >= DEPTH_QS_CHECKS)
96       phasePtr = QsearchWithChecksTable;
97   else
98   {
99       phasePtr = QsearchWithoutChecksTable;
100
101       // Skip TT move if is not a capture or a promotion, this avoids
102       // qsearch tree explosion due to a possible perpetual check or
103       // similar rare cases when TT table is full.
104       if (ttm != MOVE_NONE && !pos.move_is_capture(ttm) && !move_is_promotion(ttm))
105           ttm = MOVE_NONE;
106   }
107
108   ttMove = (ttm && pos.move_is_pl(ttm) ? ttm : MOVE_NONE);
109   phasePtr += int(ttMove == MOVE_NONE) - 1;
110   go_next_phase();
111 }
112
113 MovePicker::MovePicker(const Position& p, Move ttm, const History& h, int parentCapture)
114                        : pos(p), H(h) {
115
116   assert (!pos.in_check());
117
118   // In ProbCut we consider only captures better than parent's move
119   captureThreshold = parentCapture;
120   phasePtr = ProbCutTable;
121
122   if (   ttm != MOVE_NONE
123       && (!pos.move_is_capture(ttm) ||  pos.see(ttm) <= captureThreshold))
124       ttm = MOVE_NONE;
125
126   ttMove = (ttm && pos.move_is_pl(ttm) ? ttm : MOVE_NONE);
127   phasePtr += int(ttMove == MOVE_NONE) - 1;
128   go_next_phase();
129 }
130
131
132 /// MovePicker::go_next_phase() generates, scores and sorts the next bunch
133 /// of moves when there are no more moves to try for the current phase.
134
135 void MovePicker::go_next_phase() {
136
137   curMove = moves;
138   phase = *(++phasePtr);
139   switch (phase) {
140
141   case PH_TT_MOVE:
142       lastMove = curMove + 1;
143       return;
144
145   case PH_GOOD_CAPTURES:
146   case PH_GOOD_PROBCUT:
147       lastMove = generate<MV_CAPTURE>(pos, moves);
148       score_captures();
149       return;
150
151   case PH_KILLERS:
152       curMove = killers;
153       lastMove = curMove + 2;
154       return;
155
156   case PH_NONCAPTURES_1:
157       lastNonCapture = lastMove = generate<MV_NON_CAPTURE>(pos, moves);
158       score_noncaptures();
159       sort_moves(moves, lastNonCapture, &lastMove);
160       return;
161
162   case PH_NONCAPTURES_2:
163       curMove = lastMove;
164       lastMove = lastNonCapture;
165       insertion_sort<MoveStack>(curMove, lastMove);
166       return;
167
168   case PH_BAD_CAPTURES:
169       // Bad captures SEE value is already calculated so just pick
170       // them in order to get SEE move ordering.
171       curMove = badCaptures;
172       lastMove = moves + MAX_MOVES;
173       return;
174
175   case PH_EVASIONS:
176       assert(pos.in_check());
177       lastMove = generate<MV_EVASION>(pos, moves);
178       score_evasions();
179       return;
180
181   case PH_QCAPTURES:
182       lastMove = generate<MV_CAPTURE>(pos, moves);
183       score_captures();
184       return;
185
186   case PH_QCHECKS:
187       lastMove = generate<MV_NON_CAPTURE_CHECK>(pos, moves);
188       return;
189
190   case PH_STOP:
191       lastMove = curMove + 1; // Avoid another go_next_phase() call
192       return;
193
194   default:
195       assert(false);
196       return;
197   }
198 }
199
200
201 /// MovePicker::score_captures(), MovePicker::score_noncaptures() and
202 /// MovePicker::score_evasions() assign a numerical move ordering score
203 /// to each move in a move list.  The moves with highest scores will be
204 /// picked first by get_next_move().
205
206 void MovePicker::score_captures() {
207   // Winning and equal captures in the main search are ordered by MVV/LVA.
208   // Suprisingly, this appears to perform slightly better than SEE based
209   // move ordering. The reason is probably that in a position with a winning
210   // capture, capturing a more valuable (but sufficiently defended) piece
211   // first usually doesn't hurt. The opponent will have to recapture, and
212   // the hanging piece will still be hanging (except in the unusual cases
213   // where it is possible to recapture with the hanging piece). Exchanging
214   // big pieces before capturing a hanging piece probably helps to reduce
215   // the subtree size.
216   // In main search we want to push captures with negative SEE values to
217   // badCaptures[] array, but instead of doing it now we delay till when
218   // the move has been picked up in pick_move_from_list(), this way we save
219   // some SEE calls in case we get a cutoff (idea from Pablo Vazquez).
220   Move m;
221
222   // Use MVV/LVA ordering
223   for (MoveStack* cur = moves; cur != lastMove; cur++)
224   {
225       m = cur->move;
226       if (move_is_promotion(m))
227           cur->score = QueenValueMidgame;
228       else
229           cur->score =  pos.midgame_value_of_piece_on(move_to(m))
230                       - pos.type_of_piece_on(move_from(m));
231   }
232 }
233
234 void MovePicker::score_noncaptures() {
235
236   Move m;
237   Square from;
238
239   for (MoveStack* cur = moves; cur != lastMove; cur++)
240   {
241       m = cur->move;
242       from = move_from(m);
243       cur->score = H.value(pos.piece_on(from), move_to(m));
244   }
245 }
246
247 void MovePicker::score_evasions() {
248   // Try good captures ordered by MVV/LVA, then non-captures if
249   // destination square is not under attack, ordered by history
250   // value, and at the end bad-captures and non-captures with a
251   // negative SEE. This last group is ordered by the SEE score.
252   Move m;
253   int seeScore;
254
255   // Skip if we don't have at least two moves to order
256   if (lastMove < moves + 2)
257       return;
258
259   for (MoveStack* cur = moves; cur != lastMove; cur++)
260   {
261       m = cur->move;
262       if ((seeScore = pos.see_sign(m)) < 0)
263           cur->score = seeScore - History::MaxValue; // Be sure we are at the bottom
264       else if (pos.move_is_capture(m))
265           cur->score =  pos.midgame_value_of_piece_on(move_to(m))
266                       - pos.type_of_piece_on(move_from(m)) + History::MaxValue;
267       else
268           cur->score = H.value(pos.piece_on(move_from(m)), move_to(m));
269   }
270 }
271
272 /// MovePicker::get_next_move() is the most important method of the MovePicker
273 /// class. It returns a new pseudo legal move every time it is called, until there
274 /// are no more moves left. It picks the move with the biggest score from a list
275 /// of generated moves taking care not to return the tt move if has already been
276 /// searched previously. Note that this function is not thread safe so should be
277 /// lock protected by caller when accessed through a shared MovePicker object.
278
279 Move MovePicker::get_next_move() {
280
281   Move move;
282
283   while (true)
284   {
285       while (curMove == lastMove)
286           go_next_phase();
287
288       switch (phase) {
289
290       case PH_TT_MOVE:
291           curMove++;
292           return ttMove;
293           break;
294
295       case PH_GOOD_CAPTURES:
296           move = pick_best(curMove++, lastMove).move;
297           if (move != ttMove)
298           {
299               assert(captureThreshold <= 0); // Otherwise we must use see instead of see_sign
300
301               // Check for a non negative SEE now
302               int seeValue = pos.see_sign(move);
303               if (seeValue >= captureThreshold)
304                   return move;
305
306               // Losing capture, move it to the tail of the array, note
307               // that move has now been already checked for pseudo legality.
308               (--badCaptures)->move = move;
309               badCaptures->score = seeValue;
310           }
311           break;
312
313      case PH_GOOD_PROBCUT:
314           move = pick_best(curMove++, lastMove).move;
315           if (   move != ttMove
316               && pos.see(move) > captureThreshold)
317               return move;
318           break;
319
320       case PH_KILLERS:
321           move = (curMove++)->move;
322           if (   move != MOVE_NONE
323               && pos.move_is_pl(move)
324               && move != ttMove
325               && !pos.move_is_capture(move))
326               return move;
327           break;
328
329       case PH_NONCAPTURES_1:
330       case PH_NONCAPTURES_2:
331           move = (curMove++)->move;
332           if (   move != ttMove
333               && move != killers[0].move
334               && move != killers[1].move)
335               return move;
336           break;
337
338       case PH_BAD_CAPTURES:
339           move = pick_best(curMove++, lastMove).move;
340           return move;
341
342       case PH_EVASIONS:
343       case PH_QCAPTURES:
344           move = pick_best(curMove++, lastMove).move;
345           if (move != ttMove)
346               return move;
347           break;
348
349       case PH_QCHECKS:
350           move = (curMove++)->move;
351           if (move != ttMove)
352               return move;
353           break;
354
355       case PH_STOP:
356           return MOVE_NONE;
357
358       default:
359           assert(false);
360           break;
361       }
362   }
363 }