]> git.sesse.net Git - stockfish/blob - src/movepick.cpp
Fix a couple of MSVC warnings
[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         // It's probably a good idea to use SEE move ordering here. FIXME
146         movesPicked = 0;
147         break;
148
149     case PH_NONCAPTURES:
150         numOfMoves = generate_noncaptures(pos, moves);
151         score_noncaptures();
152         std::sort(moves, moves + numOfMoves);
153         movesPicked = 0;
154         break;
155
156     case PH_EVASIONS:
157         assert(pos.is_check());
158         numOfMoves = generate_evasions(pos, moves, pinned);
159         score_evasions();
160         std::sort(moves, moves + numOfMoves);
161         movesPicked = 0;
162         break;
163
164     case PH_QCAPTURES:
165         numOfMoves = generate_captures(pos, moves);
166         score_qcaptures();
167         std::sort(moves, moves + numOfMoves);
168         movesPicked = 0;
169         break;
170
171     case PH_QCHECKS:
172         // Perhaps we should order moves move here?  FIXME
173         numOfMoves = generate_non_capture_checks(pos, moves, dc);
174         movesPicked = 0;
175         break;
176
177     case PH_STOP:
178         return MOVE_NONE;
179
180     default:
181         assert(false);
182         return MOVE_NONE;
183     }
184   }
185 }
186
187
188 /// A variant of get_next_move() which takes a lock as a parameter, used to
189 /// prevent multiple threads from picking the same move at a split point.
190
191 Move MovePicker::get_next_move(Lock &lock) {
192
193    lock_grab(&lock);
194    if (finished)
195    {
196        lock_release(&lock);
197        return MOVE_NONE;
198    }
199    Move m = get_next_move();
200    if (m == MOVE_NONE)
201        finished = true;
202
203    lock_release(&lock);
204    return m;
205 }
206
207
208 /// MovePicker::score_captures(), MovePicker::score_noncaptures(),
209 /// MovePicker::score_evasions() and MovePicker::score_qcaptures() assign a
210 /// numerical move ordering score to each move in a move list.  The moves
211 /// with highest scores will be picked first by pick_move_from_list().
212
213 void MovePicker::score_captures() {
214   // Winning and equal captures in the main search are ordered by MVV/LVA.
215   // Suprisingly, this appears to perform slightly better than SEE based
216   // move ordering.  The reason is probably that in a position with a winning
217   // capture, capturing a more valuable (but sufficiently defended) piece
218   // first usually doesn't hurt.  The opponent will have to recapture, and
219   // the hanging piece will still be hanging (except in the unusual cases
220   // where it is possible to recapture with the hanging piece). Exchanging
221   // big pieces before capturing a hanging piece probably helps to reduce
222   // the subtree size.
223   // While scoring captures it moves all captures with negative SEE values
224   // to the badCaptures[] array.
225   Move m;
226   int seeValue;
227
228   for (int i = 0; i < numOfMoves; i++)
229   {
230       m = moves[i].move;
231       seeValue = pos.see(m);
232       if (seeValue >= 0)
233       {
234           if (move_promotion(m))
235               moves[i].score = QueenValueMidgame;
236           else
237               moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
238                               -int(pos.type_of_piece_on(move_from(m)));
239       }
240       else
241       {
242           // Losing capture, move it to the badCaptures[] array
243           assert(numOfBadCaptures < 63);
244           moves[i].score = seeValue;
245           badCaptures[numOfBadCaptures++] = moves[i];
246           moves[i--] = moves[--numOfMoves];
247       }
248   }
249 }
250
251 void MovePicker::score_noncaptures() {
252   // First score by history, when no history is available then use
253   // piece/square tables values. This seems to be better then a
254   // random choice when we don't have an history for any move.
255   Move m;
256   int hs;
257
258   for (int i = 0; i < numOfMoves; i++)
259   {
260       m = moves[i].move;
261
262       if (m == killer1)
263           hs = HistoryMax + 2;
264       else if (m == killer2)
265           hs = HistoryMax + 1;
266       else
267           hs = H.move_ordering_score(pos.piece_on(move_from(m)), m);
268
269       // Ensure history is always preferred to pst
270       if (hs > 0)
271           hs += 1000;
272
273       // pst based scoring
274       moves[i].score = hs + pos.mg_pst_delta(m);
275   }
276 }
277
278 void MovePicker::score_evasions() {
279
280   for (int i = 0; i < numOfMoves; i++)
281   {
282       Move m = moves[i].move;
283       if (m == ttMove)
284           moves[i].score = 2*HistoryMax;
285       else if (!pos.square_is_empty(move_to(m)))
286       {
287           int seeScore = pos.see(m);
288           moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
289       } else
290           moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
291   }
292 }
293
294 void MovePicker::score_qcaptures() {
295
296   // Use MVV/LVA ordering
297   for (int i = 0; i < numOfMoves; i++)
298   {
299       Move m = moves[i].move;
300       if (move_promotion(m))
301           moves[i].score = QueenValueMidgame;
302       else
303           moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
304                           -int(pos.type_of_piece_on(move_from(m)));
305   }
306 }
307
308
309 /// MovePicker::pick_move_from_list() picks the move with the biggest score
310 /// from a list of generated moves (moves[] or badCaptures[], depending on
311 /// the current move generation phase).  It takes care not to return the
312 /// transposition table move if that has already been serched previously.
313
314 Move MovePicker::pick_move_from_list() {
315
316   assert(movesPicked >= 0);
317   assert(!pos.is_check() || PhaseTable[phaseIndex] == PH_EVASIONS || PhaseTable[phaseIndex] == PH_STOP);
318   assert( pos.is_check() || PhaseTable[phaseIndex] != PH_EVASIONS);
319
320   switch (PhaseTable[phaseIndex]) {
321
322   case PH_GOOD_CAPTURES:
323   case PH_NONCAPTURES:
324       while (movesPicked < numOfMoves)
325       {
326           Move move = moves[movesPicked++].move;
327           if (   move != ttMove
328               && move != mateKiller
329               && pos.pl_move_is_legal(move, pinned))
330               return move;
331       }
332       break;
333
334   case PH_EVASIONS:
335       if (movesPicked < numOfMoves)
336           return moves[movesPicked++].move;
337
338       break;
339
340   case PH_BAD_CAPTURES:
341       while (movesPicked < numOfBadCaptures)
342       {
343           Move move = badCaptures[movesPicked++].move;
344           if (   move != ttMove
345               && move != mateKiller
346               && pos.pl_move_is_legal(move, pinned))
347               return move;
348       }
349       break;
350
351   case PH_QCAPTURES:
352   case PH_QCHECKS:
353       while (movesPicked < numOfMoves)
354       {
355           Move move = moves[movesPicked++].move;
356           // Maybe postpone the legality check until after futility pruning?
357           if (   move != ttMove
358               && pos.pl_move_is_legal(move, pinned))
359               return move;
360       }
361       break;
362
363   default:
364       break;
365   }
366   return MOVE_NONE;
367 }
368
369
370 /// MovePicker::init_phase_table() initializes the PhaseTable[],
371 /// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex
372 /// and QsearchWithoutChecksPhaseIndex. It is only called once during
373 /// program startup, and never again while the program is running.
374
375 void MovePicker::init_phase_table() {
376
377   int i = 0;
378
379   // Main search
380   MainSearchPhaseIndex = i - 1;
381   PhaseTable[i++] = PH_TT_MOVE;
382   PhaseTable[i++] = PH_MATE_KILLER;
383   PhaseTable[i++] = PH_GOOD_CAPTURES;
384   // PH_KILLER_1 and PH_KILLER_2 are not yet used.
385   // PhaseTable[i++] = PH_KILLER_1;
386   // PhaseTable[i++] = PH_KILLER_2;
387   PhaseTable[i++] = PH_NONCAPTURES;
388   PhaseTable[i++] = PH_BAD_CAPTURES;
389   PhaseTable[i++] = PH_STOP;
390
391   // Check evasions
392   EvasionsPhaseIndex = i - 1;
393   PhaseTable[i++] = PH_EVASIONS;
394   PhaseTable[i++] = PH_STOP;
395
396   // Quiescence search with checks
397   QsearchWithChecksPhaseIndex = i - 1;
398   PhaseTable[i++] = PH_TT_MOVE;
399   PhaseTable[i++] = PH_QCAPTURES;
400   PhaseTable[i++] = PH_QCHECKS;
401   PhaseTable[i++] = PH_STOP;
402
403   // Quiescence search without checks
404   QsearchWithoutChecksPhaseIndex = i - 1;
405   PhaseTable[i++] = PH_TT_MOVE;
406   PhaseTable[i++] = PH_QCAPTURES;
407   PhaseTable[i++] = PH_STOP;
408 }