]> git.sesse.net Git - stockfish/blob - src/movepick.cpp
Use special null move technique in low depth.
[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 LowSearchPhaseTable[]  = { PH_STOP, PH_TT_MOVES, PH_GOOD_CAPTURES, PH_NULL_MOVE, PH_KILLERS, PH_NONCAPTURES, PH_BAD_CAPTURES, PH_STOP};
49   const MovegenPhaseT EvasionsPhaseTable[] = { PH_STOP, PH_EVASIONS, PH_STOP};
50   const MovegenPhaseT QsearchWithChecksPhaseTable[] = { PH_STOP, PH_TT_MOVES, PH_QCAPTURES, PH_QCHECKS, PH_STOP};
51   const MovegenPhaseT QsearchWithoutChecksPhaseTable[] = { PH_STOP, PH_TT_MOVES, PH_QCAPTURES, PH_STOP};
52 }
53
54
55 ////
56 //// Functions
57 ////
58
59
60 /// Constructor for the MovePicker class.  Apart from the position for which
61 /// it is asked to pick legal moves, MovePicker also wants some information
62 /// to help it to return the presumably good moves first, to decide which
63 /// moves to return (in the quiescence search, for instance, we only want to
64 /// search captures, promotions and some checks) and about how important good
65 /// move ordering is at the current node.
66
67 MovePicker::MovePicker(const Position& p, Move ttm, Depth d,
68                        const History& h, SearchStack* ss, bool useNullMove) : pos(p), H(h) {
69   ttMoves[0] = ttm;
70   if (ss)
71   {
72       ttMoves[1] = (ss->mateKiller == ttm)? MOVE_NONE : ss->mateKiller;
73       killers[0] = ss->killers[0];
74       killers[1] = ss->killers[1];
75   } else
76       ttMoves[1] = killers[0] = killers[1] = MOVE_NONE;
77
78   movesPicked = numOfMoves = numOfBadCaptures = 0;
79   finished = false;
80
81   if (p.is_check())
82       phasePtr = EvasionsPhaseTable;
83   else if (d >= Depth(3 * OnePly))
84       phasePtr = useNullMove ? MainSearchPhaseTable : MainSearchNoNullPhaseTable;
85   else if (d > Depth(0))
86       phasePtr = useNullMove ? LowSearchPhaseTable : MainSearchNoNullPhaseTable;
87   else if (d == Depth(0))
88       phasePtr = QsearchWithChecksPhaseTable;
89   else
90       phasePtr = QsearchWithoutChecksPhaseTable;
91
92   Color us = pos.side_to_move();
93
94   dc = p.discovered_check_candidates(us);
95   pinned = p.pinned_pieces(us);
96 }
97
98
99 /// MovePicker::get_next_move() is the most important method of the MovePicker
100 /// class.  It returns a new legal move every time it is called, until there
101 /// are no more moves left of the types we are interested in.
102
103 Move MovePicker::get_next_move() {
104
105   Move move;
106
107   while (true)
108   {
109     // If we already have a list of generated moves, pick the best move from
110     // the list, and return it.
111     move = pick_move_from_list();
112     if (move != MOVE_NONE)
113     {
114         assert(move_is_ok(move));
115         return move;
116     }
117
118     // Next phase
119     phasePtr++;
120     switch (*phasePtr) {
121
122     case PH_NULL_MOVE:
123         return MOVE_NULL;
124
125     case PH_TT_MOVES:
126         movesPicked = 0; // This is used as index to ttMoves[]
127         break;
128
129     case PH_GOOD_CAPTURES:
130         numOfMoves = generate_captures(pos, moves);
131         score_captures();
132         std::sort(moves, moves + numOfMoves);
133         movesPicked = 0;
134         break;
135
136     case PH_KILLERS:
137         movesPicked = 0; // This is used as index to killers[]
138         break;
139
140     case PH_NONCAPTURES:
141         numOfMoves = generate_noncaptures(pos, moves);
142         score_noncaptures();
143         std::sort(moves, moves + numOfMoves);
144         movesPicked = 0;
145         break;
146
147     case PH_BAD_CAPTURES:
148         // Bad captures SEE value is already calculated so just sort them
149         // to get SEE move ordering.
150         std::sort(badCaptures, badCaptures + numOfBadCaptures);
151         movesPicked = 0;
152         break;
153
154     case PH_EVASIONS:
155         assert(pos.is_check());
156         numOfMoves = generate_evasions(pos, moves, pinned);
157         score_evasions();
158         std::sort(moves, moves + numOfMoves);
159         movesPicked = 0;
160         break;
161
162     case PH_QCAPTURES:
163         numOfMoves = generate_captures(pos, moves);
164         score_captures();
165         std::sort(moves, moves + numOfMoves);
166         movesPicked = 0;
167         break;
168
169     case PH_QCHECKS:
170         // Perhaps we should order moves move here?  FIXME
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   // In main search we want to push captures with negative SEE values to
222   // badCaptures[] array, but instead of doing it now we delay till when
223   // the move has been picked up in pick_move_from_list(), this way we save
224   // some SEE calls in case we get a cutoff (idea from Pablo Vazquez).
225   Move m;
226
227   // Use MVV/LVA ordering
228   for (int i = 0; i < numOfMoves; i++)
229   {
230       m = moves[i].move;
231       if (move_is_promotion(m))
232           moves[i].score = QueenValueMidgame;
233       else
234           moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
235                           -int(pos.type_of_piece_on(move_from(m)));
236   }
237 }
238
239 void MovePicker::score_noncaptures() {
240   // First score by history, when no history is available then use
241   // piece/square tables values. This seems to be better then a
242   // random choice when we don't have an history for any move.
243   Piece piece;
244   Square from, to;
245   int hs;
246
247   for (int i = 0; i < numOfMoves; i++)
248   {
249       from = move_from(moves[i].move);
250       to = move_to(moves[i].move);
251       piece = pos.piece_on(from);
252       hs = H.move_ordering_score(piece, to);
253
254       // Ensure history is always preferred to pst
255       if (hs > 0)
256           hs += 1000;
257
258       // pst based scoring
259       moves[i].score = hs + pos.pst_delta<Position::MidGame>(piece, from, to);
260   }
261 }
262
263 void MovePicker::score_evasions() {
264
265   for (int i = 0; i < numOfMoves; i++)
266   {
267       Move m = moves[i].move;
268       if (m == ttMoves[0])
269           moves[i].score = 2*HistoryMax;
270       else if (!pos.square_is_empty(move_to(m)))
271       {
272           int seeScore = pos.see(m);
273           moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
274       } else
275           moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), move_to(m));
276   }
277 }
278
279
280 /// MovePicker::pick_move_from_list() picks the move with the biggest score
281 /// from a list of generated moves (moves[] or badCaptures[], depending on
282 /// the current move generation phase).  It takes care not to return the
283 /// transposition table move if that has already been serched previously.
284
285 Move MovePicker::pick_move_from_list() {
286
287   assert(movesPicked >= 0);
288   assert(!pos.is_check() || *phasePtr == PH_EVASIONS || *phasePtr == PH_STOP);
289   assert( pos.is_check() || *phasePtr != PH_EVASIONS);
290
291   switch (*phasePtr) {
292
293   case PH_TT_MOVES:
294         while (movesPicked < 2) {
295             Move move = ttMoves[movesPicked++];
296             if (   move != MOVE_NONE
297                 && move_is_legal(pos, move, pinned))
298                 return move;
299         }
300         break;
301
302   case PH_GOOD_CAPTURES:
303       while (movesPicked < numOfMoves)
304       {
305           Move move = moves[movesPicked++].move;
306           if (   move != ttMoves[0]
307               && move != ttMoves[1]
308               && pos.pl_move_is_legal(move, pinned))
309           {
310               // Check for a non negative SEE now
311               int seeValue = pos.see_sign(move);
312               if (seeValue >= 0)
313                   return move;
314
315               // Losing capture, move it to the badCaptures[] array, note
316               // that move has now been already checked for legality.
317               assert(numOfBadCaptures < 63);
318               badCaptures[numOfBadCaptures].move = move;
319               badCaptures[numOfBadCaptures++].score = seeValue;
320           }
321       }
322       break;
323
324   case PH_KILLERS:
325         while (movesPicked < 2) {
326             Move move = killers[movesPicked++];
327             if (   move != MOVE_NONE
328                 && move != ttMoves[0]
329                 && move != ttMoves[1]
330                 && move_is_legal(pos, move, pinned)
331                 && !pos.move_is_capture(move))
332                 return move;
333         }
334         break;
335
336   case PH_NONCAPTURES:
337       while (movesPicked < numOfMoves)
338       {
339           Move move = moves[movesPicked++].move;
340           if (   move != ttMoves[0]
341               && move != ttMoves[1]
342               && move != killers[0]
343               && move != killers[1]
344               && pos.pl_move_is_legal(move, pinned))
345               return move;
346       }
347       break;
348
349   case PH_EVASIONS:
350       if (movesPicked < numOfMoves)
351           return moves[movesPicked++].move;
352       break;
353
354   case PH_BAD_CAPTURES:
355       if (movesPicked < numOfBadCaptures)
356           return badCaptures[movesPicked++].move;
357       break;
358
359   case PH_QCAPTURES:
360   case PH_QCHECKS:
361       while (movesPicked < numOfMoves)
362       {
363           Move move = moves[movesPicked++].move;
364           // Maybe postpone the legality check until after futility pruning?
365           if (   move != ttMoves[0]
366               && pos.pl_move_is_legal(move, pinned))
367               return move;
368       }
369       break;
370
371   default:
372       break;
373   }
374   return MOVE_NONE;
375 }