]> git.sesse.net Git - stockfish/blob - src/movepick.cpp
Little code style tweaks
[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 <cassert>
27
28 #include "history.h"
29 #include "evaluate.h"
30 #include "movegen.h"
31 #include "movepick.h"
32 #include "search.h"
33 #include "value.h"
34
35
36 ////
37 //// Local definitions
38 ////
39
40 namespace {
41
42   /// Variables
43
44   MovePicker::MovegenPhase PhaseTable[32];
45   int MainSearchPhaseIndex;
46   int EvasionsPhaseIndex;
47   int QsearchWithChecksPhaseIndex;
48   int QsearchWithoutChecksPhaseIndex;
49
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         movesPicked = 0;
141         break;
142
143     case PH_BAD_CAPTURES:
144         movesPicked = 0;
145         break;
146
147     case PH_NONCAPTURES:
148         numOfMoves = generate_noncaptures(pos, moves);
149         score_noncaptures();
150         movesPicked = 0;
151         break;
152
153     case PH_EVASIONS:
154         assert(pos.is_check());
155         numOfMoves = generate_evasions(pos, moves, pinned);
156         score_evasions();
157         movesPicked = 0;
158         break;
159
160     case PH_QCAPTURES:
161         numOfMoves = generate_captures(pos, moves);
162         score_qcaptures();
163         movesPicked = 0;
164         break;
165
166     case PH_QCHECKS:
167         numOfMoves = generate_checks(pos, moves, dc);
168         movesPicked = 0;
169         break;
170
171     case PH_STOP:
172         return MOVE_NONE;
173
174     default:
175         assert(false);
176         return MOVE_NONE;
177     }
178   }
179 }
180
181
182 /// A variant of get_next_move() which takes a lock as a parameter, used to
183 /// prevent multiple threads from picking the same move at a split point.
184
185 Move MovePicker::get_next_move(Lock &lock) {
186
187    lock_grab(&lock);
188    if (finished)
189    {
190        lock_release(&lock);
191        return MOVE_NONE;
192    }
193    Move m = get_next_move();
194    if (m == MOVE_NONE)
195        finished = true;
196
197    lock_release(&lock);
198    return m;
199 }
200
201
202 /// MovePicker::score_captures(), MovePicker::score_noncaptures(),
203 /// MovePicker::score_evasions() and MovePicker::score_qcaptures() assign a
204 /// numerical move ordering score to each move in a move list.  The moves
205 /// with highest scores will be picked first by pick_move_from_list().
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   // While scoring captures it moves all captures with negative SEE values
218   // to the badCaptures[] array.
219   Move m;
220   int seeValue;
221
222   for (int i = 0; i < numOfMoves; i++)
223   {
224       m = moves[i].move;
225       seeValue = pos.see(m);
226       if (seeValue >= 0)
227       {
228           if (move_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       else
235       {
236           // Losing capture, move it to the badCaptures[] array
237           assert(numOfBadCaptures < 63);
238           moves[i].score = seeValue;
239           badCaptures[numOfBadCaptures++] = moves[i];
240           moves[i--] = moves[--numOfMoves];
241       }
242   }
243 }
244
245 void MovePicker::score_noncaptures() {
246   // First score by history, when no history is available then use
247   // piece/square tables values. This seems to be better then a
248   // random choice when we don't have an history for any move.
249   Move m;
250   int hs;
251
252   for (int i = 0; i < numOfMoves; i++)
253   {
254       m = moves[i].move;
255
256       if (m == killer1)
257           hs = HistoryMax + 2;
258       else if (m == killer2)
259           hs = HistoryMax + 1;
260       else
261           hs = H.move_ordering_score(pos.piece_on(move_from(m)), m);
262
263       // Ensure history is always preferred to pst
264       if (hs > 0)
265           hs += 1000;
266
267       // pst based scoring
268       moves[i].score = hs + pos.mg_pst_delta(m);
269   }
270 }
271
272 void MovePicker::score_evasions() {
273
274   for (int i = 0; i < numOfMoves; i++)
275   {
276       Move m = moves[i].move;
277       if (m == ttMove)
278           moves[i].score = 2*HistoryMax;
279       else if (!pos.square_is_empty(move_to(m)))
280       {
281           int seeScore = pos.see(m);
282           moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
283       } else
284           moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
285   }
286 }
287
288 void MovePicker::score_qcaptures() {
289
290   // Use MVV/LVA ordering
291   for (int i = 0; i < numOfMoves; i++)
292   {
293       Move m = moves[i].move;
294       if (move_promotion(m))
295           moves[i].score = QueenValueMidgame;
296       else
297           moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
298                           -int(pos.type_of_piece_on(move_from(m)));
299   }
300 }
301
302
303 /// find_best_index() loops across the moves and returns index of
304 /// the highest scored one. There is also a second version that
305 /// lowers the priority of moves that attack the same square,
306 /// so that if the best move that attack a square fails the next
307 /// move picked attacks a different square if any, not the same one.
308
309 int MovePicker::find_best_index() {
310
311   assert(movesPicked < numOfMoves);
312
313   int bestIndex = movesPicked, bestScore = moves[movesPicked].score;
314
315   for (int i = movesPicked + 1; i < numOfMoves; i++)
316       if (moves[i].score > bestScore)
317       {
318           bestIndex = i;
319           bestScore = moves[i].score;
320       }
321   return bestIndex;
322 }
323
324 int MovePicker::find_best_index(Bitboard* squares, int values[]) {
325
326   assert(movesPicked < numOfMoves);
327
328   int hs;
329   Move m;
330   Square to;
331   int bestScore = -10000000, bestIndex = -1;
332
333   for (int i = movesPicked; i < numOfMoves; i++)
334   {
335       m = moves[i].move;
336       to = move_to(m);
337
338       if (!bit_is_set(*squares, to))
339       {
340           // Init at first use
341           set_bit(squares, to);
342           values[to] = 0;
343       }
344
345       hs = moves[i].score - values[to];
346       if (hs > bestScore)
347       {
348           bestIndex = i;
349           bestScore = hs;
350       }
351   }
352
353   if (bestIndex != -1)
354   {
355       // Raise value of the picked square, so next attack
356       // to the same square will get low priority.
357       to = move_to(moves[bestIndex].move);
358       values[to] += 0xB00;
359   }
360   return bestIndex;
361 }
362
363
364 /// MovePicker::pick_move_from_list() picks the move with the biggest score
365 /// from a list of generated moves (moves[] or badCaptures[], depending on
366 /// the current move generation phase).  It takes care not to return the
367 /// transposition table move if that has already been serched previously.
368
369 Move MovePicker::pick_move_from_list() {
370
371   int bestIndex;
372   Move move;
373
374   switch (PhaseTable[phaseIndex]) {
375
376   case PH_GOOD_CAPTURES:
377       assert(!pos.is_check());
378       assert(movesPicked >= 0);
379
380       while (movesPicked < numOfMoves)
381       {
382           bestIndex = find_best_index();
383           move = moves[bestIndex].move;
384           moves[bestIndex] = moves[movesPicked++];
385           if (   move != ttMove
386               && move != mateKiller
387               && pos.pl_move_is_legal(move, pinned))
388               return move;
389       }
390       break;
391
392   case PH_NONCAPTURES:
393       assert(!pos.is_check());
394       assert(movesPicked >= 0);
395
396       while (movesPicked < numOfMoves)
397       {
398           // If this is a PV node or we have only picked a few moves, scan
399           // the entire move list for the best move.  If many moves have already
400           // been searched and it is not a PV node, we are probably failing low
401           // anyway, so we just pick the first move from the list.
402           bestIndex = (pvNode || movesPicked < 12) ? find_best_index() : movesPicked;
403           move = moves[bestIndex].move;
404           moves[bestIndex] = moves[movesPicked++];
405           if (   move != ttMove
406               && move != mateKiller
407               && pos.pl_move_is_legal(move, pinned))
408               return move;
409       }
410       break;
411
412   case PH_EVASIONS:
413       assert(pos.is_check());
414       assert(movesPicked >= 0);
415
416       while (movesPicked < numOfMoves)
417       {
418           bestIndex = find_best_index();
419           move = moves[bestIndex].move;
420           moves[bestIndex] = moves[movesPicked++];
421           return move;
422     }
423     break;
424
425   case PH_BAD_CAPTURES:
426       assert(!pos.is_check());
427       assert(movesPicked >= 0);
428       // It's probably a good idea to use SEE move ordering here, instead
429       // of just picking the first move.  FIXME
430       while (movesPicked < numOfBadCaptures)
431       {
432           move = badCaptures[movesPicked++].move;
433           if (   move != ttMove
434               && move != mateKiller
435               && pos.pl_move_is_legal(move, pinned))
436               return move;
437       }
438       break;
439
440   case PH_QCAPTURES:
441       assert(!pos.is_check());
442       assert(movesPicked >= 0);
443       while (movesPicked < numOfMoves)
444       {
445           bestIndex = (movesPicked < 4 ? find_best_index() : movesPicked);
446           move = moves[bestIndex].move;
447           moves[bestIndex] = moves[movesPicked++];
448           // Remember to change the line below if we decide to hash the qsearch!
449           // Maybe also postpone the legality check until after futility pruning?
450           if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
451               return move;
452       }
453       break;
454
455   case PH_QCHECKS:
456       assert(!pos.is_check());
457       assert(movesPicked >= 0);
458       // Perhaps we should do something better than just picking the first
459       // move here?  FIXME
460       while (movesPicked < numOfMoves)
461       {
462           move = moves[movesPicked++].move;
463           // Remember to change the line below if we decide to hash the qsearch!
464           if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
465               return move;
466       }
467       break;
468
469   default:
470       break;
471   }
472   return MOVE_NONE;
473 }
474
475
476 /// MovePicker::current_move_type() returns the type of the just
477 /// picked next move. It can be used in search to further differentiate
478 /// according to the current move type: capture, non capture, escape, etc.
479 MovePicker::MovegenPhase MovePicker::current_move_type() const {
480
481   return PhaseTable[phaseIndex];
482 }
483
484
485 /// MovePicker::init_phase_table() initializes the PhaseTable[],
486 /// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex
487 /// QsearchNoCapturesPhaseIndex, QsearchWithoutChecksPhaseIndex and
488 /// NoMovesPhaseIndex variables. It is only called once during program
489 /// startup, and never again while the program is running.
490
491 void MovePicker::init_phase_table() {
492
493   int i = 0;
494
495   // Main search
496   MainSearchPhaseIndex = i - 1;
497   PhaseTable[i++] = PH_TT_MOVE;
498   PhaseTable[i++] = PH_MATE_KILLER;
499   PhaseTable[i++] = PH_GOOD_CAPTURES;
500   // PH_KILLER_1 and PH_KILLER_2 are not yet used.
501   // PhaseTable[i++] = PH_KILLER_1;
502   // PhaseTable[i++] = PH_KILLER_2;
503   PhaseTable[i++] = PH_NONCAPTURES;
504   PhaseTable[i++] = PH_BAD_CAPTURES;
505   PhaseTable[i++] = PH_STOP;
506
507   // Check evasions
508   EvasionsPhaseIndex = i - 1;
509   PhaseTable[i++] = PH_EVASIONS;
510   PhaseTable[i++] = PH_STOP;
511
512   // Quiescence search with checks
513   QsearchWithChecksPhaseIndex = i - 1;
514   PhaseTable[i++] = PH_QCAPTURES;
515   PhaseTable[i++] = PH_QCHECKS;
516   PhaseTable[i++] = PH_STOP;
517
518   // Quiescence search without checks
519   QsearchWithoutChecksPhaseIndex = i - 1;
520   PhaseTable[i++] = PH_QCAPTURES;
521   PhaseTable[i++] = PH_STOP;
522
523 }