]> git.sesse.net Git - stockfish/blob - src/movepick.cpp
Retire some unused functions
[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), depth(d) {
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       if (depth >= 3 * ONE_PLY)
166           insertion_sort<MoveStack>(curMove, lastMove);
167       return;
168
169   case PH_BAD_CAPTURES:
170       // Bad captures SEE value is already calculated so just pick
171       // them in order to get SEE move ordering.
172       curMove = badCaptures;
173       lastMove = moves + MAX_MOVES;
174       return;
175
176   case PH_EVASIONS:
177       assert(pos.in_check());
178       lastMove = generate<MV_EVASION>(pos, moves);
179       score_evasions();
180       return;
181
182   case PH_QCAPTURES:
183       lastMove = generate<MV_CAPTURE>(pos, moves);
184       score_captures();
185       return;
186
187   case PH_QCHECKS:
188       lastMove = generate<MV_NON_CAPTURE_CHECK>(pos, moves);
189       return;
190
191   case PH_STOP:
192       lastMove = curMove + 1; // Avoid another go_next_phase() call
193       return;
194
195   default:
196       assert(false);
197       return;
198   }
199 }
200
201
202 /// MovePicker::score_captures(), MovePicker::score_noncaptures() and
203 /// MovePicker::score_evasions() assign a numerical move ordering score
204 /// to each move in a move list.  The moves with highest scores will be
205 /// picked first by get_next_move().
206
207 void MovePicker::score_captures() {
208   // Winning and equal captures in the main search are ordered by MVV/LVA.
209   // Suprisingly, this appears to perform slightly better than SEE based
210   // move ordering. The reason is probably that in a position with a winning
211   // capture, capturing a more valuable (but sufficiently defended) piece
212   // first usually doesn't hurt. The opponent will have to recapture, and
213   // the hanging piece will still be hanging (except in the unusual cases
214   // where it is possible to recapture with the hanging piece). Exchanging
215   // big pieces before capturing a hanging piece probably helps to reduce
216   // the subtree size.
217   // In main search we want to push captures with negative SEE values to
218   // badCaptures[] array, but instead of doing it now we delay till when
219   // the move has been picked up in pick_move_from_list(), this way we save
220   // some SEE calls in case we get a cutoff (idea from Pablo Vazquez).
221   Move m;
222
223   // Use MVV/LVA ordering
224   for (MoveStack* cur = moves; cur != lastMove; cur++)
225   {
226       m = cur->move;
227       if (move_is_promotion(m))
228           cur->score = QueenValueMidgame;
229       else
230           cur->score =  pos.midgame_value_of_piece_on(move_to(m))
231                       - pos.type_of_piece_on(move_from(m));
232   }
233 }
234
235 void MovePicker::score_noncaptures() {
236
237   Move m;
238   Square from;
239
240   for (MoveStack* cur = moves; cur != lastMove; cur++)
241   {
242       m = cur->move;
243       from = move_from(m);
244       cur->score = H.value(pos.piece_on(from), move_to(m));
245   }
246 }
247
248 void MovePicker::score_evasions() {
249   // Try good captures ordered by MVV/LVA, then non-captures if
250   // destination square is not under attack, ordered by history
251   // value, and at the end bad-captures and non-captures with a
252   // negative SEE. This last group is ordered by the SEE score.
253   Move m;
254   int seeScore;
255
256   // Skip if we don't have at least two moves to order
257   if (lastMove < moves + 2)
258       return;
259
260   for (MoveStack* cur = moves; cur != lastMove; cur++)
261   {
262       m = cur->move;
263       if ((seeScore = pos.see_sign(m)) < 0)
264           cur->score = seeScore - History::MaxValue; // Be sure we are at the bottom
265       else if (pos.move_is_capture(m))
266           cur->score =  pos.midgame_value_of_piece_on(move_to(m))
267                       - pos.type_of_piece_on(move_from(m)) + History::MaxValue;
268       else
269           cur->score = H.value(pos.piece_on(move_from(m)), move_to(m));
270   }
271 }
272
273 /// MovePicker::get_next_move() is the most important method of the MovePicker
274 /// class. It returns a new pseudo legal move every time it is called, until there
275 /// are no more moves left. It picks the move with the biggest score from a list
276 /// of generated moves taking care not to return the tt move if has already been
277 /// searched previously. Note that this function is not thread safe so should be
278 /// lock protected by caller when accessed through a shared MovePicker object.
279
280 Move MovePicker::get_next_move() {
281
282   Move move;
283
284   while (true)
285   {
286       while (curMove == lastMove)
287           go_next_phase();
288
289       switch (phase) {
290
291       case PH_TT_MOVE:
292           curMove++;
293           return ttMove;
294           break;
295
296       case PH_GOOD_CAPTURES:
297           move = pick_best(curMove++, lastMove).move;
298           if (move != ttMove)
299           {
300               assert(captureThreshold <= 0); // Otherwise we must use see instead of see_sign
301
302               // Check for a non negative SEE now
303               int seeValue = pos.see_sign(move);
304               if (seeValue >= captureThreshold)
305                   return move;
306
307               // Losing capture, move it to the tail of the array, note
308               // that move has now been already checked for pseudo legality.
309               (--badCaptures)->move = move;
310               badCaptures->score = seeValue;
311           }
312           break;
313
314      case PH_GOOD_PROBCUT:
315           move = pick_best(curMove++, lastMove).move;
316           if (   move != ttMove
317               && pos.see(move) > captureThreshold)
318               return move;
319           break;
320
321       case PH_KILLERS:
322           move = (curMove++)->move;
323           if (   move != MOVE_NONE
324               && pos.move_is_pl(move)
325               && move != ttMove
326               && !pos.move_is_capture(move))
327               return move;
328           break;
329
330       case PH_NONCAPTURES_1:
331       case PH_NONCAPTURES_2:
332           move = (curMove++)->move;
333           if (   move != ttMove
334               && move != killers[0].move
335               && move != killers[1].move)
336               return move;
337           break;
338
339       case PH_BAD_CAPTURES:
340           move = pick_best(curMove++, lastMove).move;
341           return move;
342
343       case PH_EVASIONS:
344       case PH_QCAPTURES:
345           move = pick_best(curMove++, lastMove).move;
346           if (move != ttMove)
347               return move;
348           break;
349
350       case PH_QCHECKS:
351           move = (curMove++)->move;
352           if (move != ttMove)
353               return move;
354           break;
355
356       case PH_STOP:
357           return MOVE_NONE;
358
359       default:
360           assert(false);
361           break;
362       }
363   }
364 }