]> git.sesse.net Git - stockfish/blob - src/movepick.cpp
Sort moves just after scoring
[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 Marco Costalba
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
22 ////
23 //// Includes
24 ////
25
26 #include <algorithm>
27 #include <cassert>
28
29 #include "history.h"
30 #include "evaluate.h"
31 #include "movegen.h"
32 #include "movepick.h"
33 #include "search.h"
34 #include "value.h"
35
36
37 ////
38 //// Local definitions
39 ////
40
41 namespace {
42
43   /// Variables
44
45   MovePicker::MovegenPhase PhaseTable[32];
46   int MainSearchPhaseIndex;
47   int EvasionsPhaseIndex;
48   int QsearchWithChecksPhaseIndex;
49   int QsearchWithoutChecksPhaseIndex;
50
51 }
52
53
54 ////
55 //// Functions
56 ////
57
58
59 /// Constructor for the MovePicker class.  Apart from the position for which
60 /// it is asked to pick legal moves, MovePicker also wants some information
61 /// to help it to return the presumably good moves first, to decide which
62 /// moves to return (in the quiescence search, for instance, we only want to
63 /// search captures, promotions and some checks) and about how important good
64 /// move ordering is at the current node.
65
66 MovePicker::MovePicker(const Position& p, bool pv, Move ttm,
67                        const SearchStack& ss, Depth d) : pos(p) {
68   pvNode = pv;
69   ttMove = ttm;
70   mateKiller = (ss.mateKiller == ttm)? MOVE_NONE : ss.mateKiller;
71   killer1 = ss.killers[0];
72   killer2 = ss.killers[1];
73   depth = d;
74   movesPicked = 0;
75   numOfMoves = 0;
76   numOfBadCaptures = 0;
77
78   if (p.is_check())
79       phaseIndex = EvasionsPhaseIndex;
80   else if (depth > Depth(0))
81       phaseIndex = MainSearchPhaseIndex;
82   else if (depth == Depth(0))
83       phaseIndex = QsearchWithChecksPhaseIndex;
84   else
85       phaseIndex = QsearchWithoutChecksPhaseIndex;
86
87   Color us = pos.side_to_move();
88
89   dc = p.discovered_check_candidates(us);
90   pinned = p.pinned_pieces(us);
91
92   finished = false;
93 }
94
95
96 /// MovePicker::get_next_move() is the most important method of the MovePicker
97 /// class.  It returns a new legal move every time it is called, until there
98 /// are no more moves left of the types we are interested in.
99
100 Move MovePicker::get_next_move() {
101
102   Move move;
103
104   while (true)
105   {
106     // If we already have a list of generated moves, pick the best move from
107     // the list, and return it.
108     move = pick_move_from_list();
109     if (move != MOVE_NONE)
110     {
111         assert(move_is_ok(move));
112         return move;
113     }
114
115     // Next phase
116     phaseIndex++;
117     switch (PhaseTable[phaseIndex]) {
118
119     case PH_TT_MOVE:
120         if (ttMove != MOVE_NONE)
121         {
122             assert(move_is_ok(ttMove));
123             if (move_is_legal(pos, ttMove, pinned))
124                 return ttMove;
125         }
126         break;
127
128     case PH_MATE_KILLER:
129         if (mateKiller != MOVE_NONE)
130         {
131             assert(move_is_ok(mateKiller));
132             if (move_is_legal(pos, mateKiller, pinned))
133                 return mateKiller;
134         }
135         break;
136
137     case PH_GOOD_CAPTURES:
138         numOfMoves = generate_captures(pos, moves);
139         score_captures();
140         std::sort(moves, moves + numOfMoves);
141         movesPicked = 0;
142         break;
143
144     case PH_BAD_CAPTURES:
145         movesPicked = 0;
146         break;
147
148     case PH_NONCAPTURES:
149         numOfMoves = generate_noncaptures(pos, moves);
150         score_noncaptures();
151         std::sort(moves, moves + numOfMoves);
152         movesPicked = 0;
153         break;
154
155     case PH_EVASIONS:
156         assert(pos.is_check());
157         numOfMoves = generate_evasions(pos, moves, pinned);
158         score_evasions();
159         std::sort(moves, moves + numOfMoves);
160         movesPicked = 0;
161         break;
162
163     case PH_QCAPTURES:
164         numOfMoves = generate_captures(pos, moves);
165         score_qcaptures();
166         std::sort(moves, moves + numOfMoves);
167         movesPicked = 0;
168         break;
169
170     case PH_QCHECKS:
171         numOfMoves = generate_non_capture_checks(pos, moves, dc);
172         movesPicked = 0;
173         break;
174
175     case PH_STOP:
176         return MOVE_NONE;
177
178     default:
179         assert(false);
180         return MOVE_NONE;
181     }
182   }
183 }
184
185
186 /// A variant of get_next_move() which takes a lock as a parameter, used to
187 /// prevent multiple threads from picking the same move at a split point.
188
189 Move MovePicker::get_next_move(Lock &lock) {
190
191    lock_grab(&lock);
192    if (finished)
193    {
194        lock_release(&lock);
195        return MOVE_NONE;
196    }
197    Move m = get_next_move();
198    if (m == MOVE_NONE)
199        finished = true;
200
201    lock_release(&lock);
202    return m;
203 }
204
205
206 /// MovePicker::score_captures(), MovePicker::score_noncaptures(),
207 /// MovePicker::score_evasions() and MovePicker::score_qcaptures() assign a
208 /// numerical move ordering score to each move in a move list.  The moves
209 /// with highest scores will be picked first by pick_move_from_list().
210
211 void MovePicker::score_captures() {
212   // Winning and equal captures in the main search are ordered by MVV/LVA.
213   // Suprisingly, this appears to perform slightly better than SEE based
214   // move ordering.  The reason is probably that in a position with a winning
215   // capture, capturing a more valuable (but sufficiently defended) piece
216   // first usually doesn't hurt.  The opponent will have to recapture, and
217   // the hanging piece will still be hanging (except in the unusual cases
218   // where it is possible to recapture with the hanging piece). Exchanging
219   // big pieces before capturing a hanging piece probably helps to reduce
220   // the subtree size.
221   // While scoring captures it moves all captures with negative SEE values
222   // to the badCaptures[] array.
223   Move m;
224   int seeValue;
225
226   for (int i = 0; i < numOfMoves; i++)
227   {
228       m = moves[i].move;
229       seeValue = pos.see(m);
230       if (seeValue >= 0)
231       {
232           if (move_promotion(m))
233               moves[i].score = QueenValueMidgame;
234           else
235               moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
236                               -int(pos.type_of_piece_on(move_from(m)));
237       }
238       else
239       {
240           // Losing capture, move it to the badCaptures[] array
241           assert(numOfBadCaptures < 63);
242           moves[i].score = seeValue;
243           badCaptures[numOfBadCaptures++] = moves[i];
244           moves[i--] = moves[--numOfMoves];
245       }
246   }
247 }
248
249 void MovePicker::score_noncaptures() {
250   // First score by history, when no history is available then use
251   // piece/square tables values. This seems to be better then a
252   // random choice when we don't have an history for any move.
253   Move m;
254   int hs;
255
256   for (int i = 0; i < numOfMoves; i++)
257   {
258       m = moves[i].move;
259
260       if (m == killer1)
261           hs = HistoryMax + 2;
262       else if (m == killer2)
263           hs = HistoryMax + 1;
264       else
265           hs = H.move_ordering_score(pos.piece_on(move_from(m)), m);
266
267       // Ensure history is always preferred to pst
268       if (hs > 0)
269           hs += 1000;
270
271       // pst based scoring
272       moves[i].score = hs + pos.mg_pst_delta(m);
273   }
274 }
275
276 void MovePicker::score_evasions() {
277
278   for (int i = 0; i < numOfMoves; i++)
279   {
280       Move m = moves[i].move;
281       if (m == ttMove)
282           moves[i].score = 2*HistoryMax;
283       else if (!pos.square_is_empty(move_to(m)))
284       {
285           int seeScore = pos.see(m);
286           moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
287       } else
288           moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
289   }
290 }
291
292 void MovePicker::score_qcaptures() {
293
294   // Use MVV/LVA ordering
295   for (int i = 0; i < numOfMoves; i++)
296   {
297       Move m = moves[i].move;
298       if (move_promotion(m))
299           moves[i].score = QueenValueMidgame;
300       else
301           moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
302                           -int(pos.type_of_piece_on(move_from(m)));
303   }
304 }
305
306
307 /// MovePicker::pick_move_from_list() picks the move with the biggest score
308 /// from a list of generated moves (moves[] or badCaptures[], depending on
309 /// the current move generation phase).  It takes care not to return the
310 /// transposition table move if that has already been serched previously.
311
312 Move MovePicker::pick_move_from_list() {
313
314   Move move;
315
316   switch (PhaseTable[phaseIndex]) {
317
318   case PH_GOOD_CAPTURES:
319       assert(!pos.is_check());
320       assert(movesPicked >= 0);
321
322       while (movesPicked < numOfMoves)
323       {
324           move = moves[movesPicked++].move;
325           if (   move != ttMove
326               && move != mateKiller
327               && pos.pl_move_is_legal(move, pinned))
328               return move;
329       }
330       break;
331
332   case PH_NONCAPTURES:
333       assert(!pos.is_check());
334       assert(movesPicked >= 0);
335
336       while (movesPicked < numOfMoves)
337       {
338           move = moves[movesPicked++].move;
339           if (   move != ttMove
340               && move != mateKiller
341               && pos.pl_move_is_legal(move, pinned))
342               return move;
343       }
344       break;
345
346   case PH_EVASIONS:
347       assert(pos.is_check());
348       assert(movesPicked >= 0);
349
350       while (movesPicked < numOfMoves)
351       {
352           move = moves[movesPicked++].move;
353           return move;
354     }
355     break;
356
357   case PH_BAD_CAPTURES:
358       assert(!pos.is_check());
359       assert(movesPicked >= 0);
360       // It's probably a good idea to use SEE move ordering here, instead
361       // of just picking the first move.  FIXME
362       while (movesPicked < numOfBadCaptures)
363       {
364           move = badCaptures[movesPicked++].move;
365           if (   move != ttMove
366               && move != mateKiller
367               && pos.pl_move_is_legal(move, pinned))
368               return move;
369       }
370       break;
371
372   case PH_QCAPTURES:
373       assert(!pos.is_check());
374       assert(movesPicked >= 0);
375
376       while (movesPicked < numOfMoves)
377       {
378           move = moves[movesPicked++].move;
379           // Maybe postpone the legality check until after futility pruning?
380           if (   move != ttMove
381               && pos.pl_move_is_legal(move, pinned))
382               return move;
383       }
384       break;
385
386   case PH_QCHECKS:
387       assert(!pos.is_check());
388       assert(movesPicked >= 0);
389       // Perhaps we should do something better than just picking the first
390       // move here?  FIXME
391       while (movesPicked < numOfMoves)
392       {
393           move = moves[movesPicked++].move;
394           if (   move != ttMove
395               && pos.pl_move_is_legal(move, pinned))
396               return move;
397       }
398       break;
399
400   default:
401       break;
402   }
403   return MOVE_NONE;
404 }
405
406
407 /// MovePicker::init_phase_table() initializes the PhaseTable[],
408 /// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex
409 /// and QsearchWithoutChecksPhaseIndex. It is only called once during
410 /// program startup, and never again while the program is running.
411
412 void MovePicker::init_phase_table() {
413
414   int i = 0;
415
416   // Main search
417   MainSearchPhaseIndex = i - 1;
418   PhaseTable[i++] = PH_TT_MOVE;
419   PhaseTable[i++] = PH_MATE_KILLER;
420   PhaseTable[i++] = PH_GOOD_CAPTURES;
421   // PH_KILLER_1 and PH_KILLER_2 are not yet used.
422   // PhaseTable[i++] = PH_KILLER_1;
423   // PhaseTable[i++] = PH_KILLER_2;
424   PhaseTable[i++] = PH_NONCAPTURES;
425   PhaseTable[i++] = PH_BAD_CAPTURES;
426   PhaseTable[i++] = PH_STOP;
427
428   // Check evasions
429   EvasionsPhaseIndex = i - 1;
430   PhaseTable[i++] = PH_EVASIONS;
431   PhaseTable[i++] = PH_STOP;
432
433   // Quiescence search with checks
434   QsearchWithChecksPhaseIndex = i - 1;
435   PhaseTable[i++] = PH_TT_MOVE;
436   PhaseTable[i++] = PH_QCAPTURES;
437   PhaseTable[i++] = PH_QCHECKS;
438   PhaseTable[i++] = PH_STOP;
439
440   // Quiescence search without checks
441   QsearchWithoutChecksPhaseIndex = i - 1;
442   PhaseTable[i++] = PH_TT_MOVE;
443   PhaseTable[i++] = PH_QCAPTURES;
444   PhaseTable[i++] = PH_STOP;
445 }