]> git.sesse.net Git - stockfish/blob - src/movepick.cpp
8089345546a1f1c58c31a8f3365fe0f2cf388c24
[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-2009 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   CACHE_LINE_ALIGNMENT
46   const MovegenPhaseT MainSearchPhaseTable[] = { PH_STOP, PH_NULL_MOVE, PH_TT_MOVES, PH_GOOD_CAPTURES, PH_KILLERS, PH_NONCAPTURES, PH_BAD_CAPTURES, PH_STOP};
47   const MovegenPhaseT MainSearchNoNullPhaseTable[] = { PH_STOP, PH_TT_MOVES, PH_GOOD_CAPTURES, PH_KILLERS, PH_NONCAPTURES, PH_BAD_CAPTURES, PH_STOP};
48   const MovegenPhaseT EvasionsPhaseTable[] = { PH_STOP, PH_EVASIONS, PH_STOP};
49   const MovegenPhaseT QsearchWithChecksPhaseTable[] = { PH_STOP, PH_TT_MOVES, PH_QCAPTURES, PH_QCHECKS, PH_STOP};
50   const MovegenPhaseT QsearchWithoutChecksPhaseTable[] = { PH_STOP, PH_TT_MOVES, PH_QCAPTURES, PH_STOP};
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, Move ttm, Depth d,
67                        const History& h, SearchStack* ss, bool useNullMove) : pos(p), H(h) {
68   ttMoves[0] = ttm;
69   if (ss)
70   {
71       ttMoves[1] = (ss->mateKiller == ttm)? MOVE_NONE : ss->mateKiller;
72       killers[0] = ss->killers[0];
73       killers[1] = ss->killers[1];
74   } else
75       ttMoves[1] = killers[0] = killers[1] = MOVE_NONE;
76
77   movesPicked = numOfMoves = numOfBadCaptures = 0;
78   finished = false;
79
80   if (p.is_check())
81       phasePtr = EvasionsPhaseTable;
82   else if (d > Depth(0))
83       phasePtr = useNullMove ? MainSearchPhaseTable : MainSearchNoNullPhaseTable;
84   else if (d == Depth(0))
85       phasePtr = QsearchWithChecksPhaseTable;
86   else
87       phasePtr = QsearchWithoutChecksPhaseTable;
88
89   Color us = pos.side_to_move();
90
91   dc = p.discovered_check_candidates(us);
92   pinned = p.pinned_pieces(us);
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     phasePtr++;
117     switch (*phasePtr) {
118
119     case PH_NULL_MOVE:
120         return MOVE_NULL;
121
122     case PH_TT_MOVES:
123         movesPicked = 0; // This is used as index to ttMoves[]
124         break;
125
126     case PH_GOOD_CAPTURES:
127         numOfMoves = generate_captures(pos, moves);
128         score_captures();
129         std::sort(moves, moves + numOfMoves);
130         movesPicked = 0;
131         break;
132
133     case PH_KILLERS:
134         movesPicked = 0; // This is used as index to killers[]
135         break;
136
137     case PH_NONCAPTURES:
138         numOfMoves = generate_noncaptures(pos, moves);
139         score_noncaptures();
140         std::sort(moves, moves + numOfMoves);
141         movesPicked = 0;
142         break;
143
144     case PH_BAD_CAPTURES:
145         // Bad captures SEE value is already calculated so just sort them
146         // to get SEE move ordering.
147         std::sort(badCaptures, badCaptures + numOfBadCaptures);
148         movesPicked = 0;
149         break;
150
151     case PH_EVASIONS:
152         assert(pos.is_check());
153         numOfMoves = generate_evasions(pos, moves, pinned);
154         score_evasions();
155         std::sort(moves, moves + numOfMoves);
156         movesPicked = 0;
157         break;
158
159     case PH_QCAPTURES:
160         numOfMoves = generate_captures(pos, moves);
161         score_captures();
162         std::sort(moves, moves + numOfMoves);
163         movesPicked = 0;
164         break;
165
166     case PH_QCHECKS:
167         // Perhaps we should order moves move here?  FIXME
168         numOfMoves = generate_non_capture_checks(pos, moves, dc);
169         movesPicked = 0;
170         break;
171
172     case PH_STOP:
173         return MOVE_NONE;
174
175     default:
176         assert(false);
177         return MOVE_NONE;
178     }
179   }
180 }
181
182
183 /// A variant of get_next_move() which takes a lock as a parameter, used to
184 /// prevent multiple threads from picking the same move at a split point.
185
186 Move MovePicker::get_next_move(Lock &lock) {
187
188    lock_grab(&lock);
189    if (finished)
190    {
191        lock_release(&lock);
192        return MOVE_NONE;
193    }
194    Move m = get_next_move();
195    if (m == MOVE_NONE)
196        finished = true;
197
198    lock_release(&lock);
199    return m;
200 }
201
202
203 /// MovePicker::score_captures(), MovePicker::score_noncaptures(),
204 /// MovePicker::score_evasions() and MovePicker::score_qcaptures() assign a
205 /// numerical move ordering score to each move in a move list.  The moves
206 /// with highest scores will be picked first by pick_move_from_list().
207
208 void MovePicker::score_captures() {
209   // Winning and equal captures in the main search are ordered by MVV/LVA.
210   // Suprisingly, this appears to perform slightly better than SEE based
211   // move ordering. The reason is probably that in a position with a winning
212   // capture, capturing a more valuable (but sufficiently defended) piece
213   // first usually doesn't hurt. The opponent will have to recapture, and
214   // the hanging piece will still be hanging (except in the unusual cases
215   // where it is possible to recapture with the hanging piece). Exchanging
216   // big pieces before capturing a hanging piece probably helps to reduce
217   // the subtree size.
218   // In main search we want to push captures with negative SEE values to
219   // badCaptures[] array, but instead of doing it now we delay till when
220   // the move has been picked up in pick_move_from_list(), this way we save
221   // some SEE calls in case we get a cutoff (idea from Pablo Vazquez).
222   Move m;
223
224   // Use MVV/LVA ordering
225   for (int i = 0; i < numOfMoves; i++)
226   {
227       m = moves[i].move;
228       if (move_is_promotion(m))
229           moves[i].score = QueenValueMidgame;
230       else
231           moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
232                           -int(pos.type_of_piece_on(move_from(m)));
233   }
234 }
235
236 void MovePicker::score_noncaptures() {
237   // First score by history, when no history is available then use
238   // piece/square tables values. This seems to be better then a
239   // random choice when we don't have an history for any move.
240   Piece piece;
241   Square from, to;
242   int hs;
243
244   for (int i = 0; i < numOfMoves; i++)
245   {
246       from = move_from(moves[i].move);
247       to = move_to(moves[i].move);
248       piece = pos.piece_on(from);
249       hs = H.move_ordering_score(piece, to);
250
251       // Ensure history is always preferred to pst
252       if (hs > 0)
253           hs += 1000;
254
255       // pst based scoring
256       moves[i].score = hs + pos.pst_delta<Position::MidGame>(piece, from, to);
257   }
258 }
259
260 void MovePicker::score_evasions() {
261
262   for (int i = 0; i < numOfMoves; i++)
263   {
264       Move m = moves[i].move;
265       if (m == ttMoves[0])
266           moves[i].score = 2*HistoryMax;
267       else if (!pos.square_is_empty(move_to(m)))
268       {
269           int seeScore = pos.see(m);
270           moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
271       } else
272           moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), move_to(m));
273   }
274 }
275
276
277 /// MovePicker::pick_move_from_list() picks the move with the biggest score
278 /// from a list of generated moves (moves[] or badCaptures[], depending on
279 /// the current move generation phase).  It takes care not to return the
280 /// transposition table move if that has already been serched previously.
281
282 Move MovePicker::pick_move_from_list() {
283
284   assert(movesPicked >= 0);
285   assert(!pos.is_check() || *phasePtr == PH_EVASIONS || *phasePtr == PH_STOP);
286   assert( pos.is_check() || *phasePtr != PH_EVASIONS);
287
288   switch (*phasePtr) {
289
290   case PH_TT_MOVES:
291         while (movesPicked < 2) {
292             Move move = ttMoves[movesPicked++];
293             if (   move != MOVE_NONE
294                 && move_is_legal(pos, move, pinned))
295                 return move;
296         }
297         break;
298
299   case PH_GOOD_CAPTURES:
300       while (movesPicked < numOfMoves)
301       {
302           Move move = moves[movesPicked++].move;
303           if (   move != ttMoves[0]
304               && move != ttMoves[1]
305               && pos.pl_move_is_legal(move, pinned))
306           {
307               // Check for a non negative SEE now
308               int seeValue = pos.see_sign(move);
309               if (seeValue >= 0)
310                   return move;
311
312               // Losing capture, move it to the badCaptures[] array, note
313               // that move has now been already checked for legality.
314               assert(numOfBadCaptures < 63);
315               badCaptures[numOfBadCaptures].move = move;
316               badCaptures[numOfBadCaptures++].score = seeValue;
317           }
318       }
319       break;
320
321   case PH_KILLERS:
322         while (movesPicked < 2) {
323             Move move = killers[movesPicked++];
324             if (   move != MOVE_NONE
325                 && move != ttMoves[0]
326                 && move != ttMoves[1]
327                 && move_is_legal(pos, move, pinned)
328                 && !pos.move_is_capture(move))
329                 return move;
330         }
331         break;
332
333   case PH_NONCAPTURES:
334       while (movesPicked < numOfMoves)
335       {
336           Move move = moves[movesPicked++].move;
337           if (   move != ttMoves[0]
338               && move != ttMoves[1]
339               && move != killers[0]
340               && move != killers[1]
341               && pos.pl_move_is_legal(move, pinned))
342               return move;
343       }
344       break;
345
346   case PH_EVASIONS:
347       if (movesPicked < numOfMoves)
348           return moves[movesPicked++].move;
349       break;
350
351   case PH_BAD_CAPTURES:
352       if (movesPicked < numOfBadCaptures)
353           return badCaptures[movesPicked++].move;
354       break;
355
356   case PH_QCAPTURES:
357   case PH_QCHECKS:
358       while (movesPicked < numOfMoves)
359       {
360           Move move = moves[movesPicked++].move;
361           // Maybe postpone the legality check until after futility pruning?
362           if (   move != ttMoves[0]
363               && pos.pl_move_is_legal(move, pinned))
364               return move;
365       }
366       break;
367
368   default:
369       break;
370   }
371   return MOVE_NONE;
372 }