]> git.sesse.net Git - stockfish/blob - src/move.h
Micro-optimize castling handling in do_move()
[stockfish] / src / move.h
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-2010 Marco Costalba, Joona Kiiski, Tord Romstad
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   Stockfish is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #if !defined(MOVE_H_INCLUDED)
21 #define MOVE_H_INCLUDED
22
23 #include <string>
24
25 #include "misc.h"
26 #include "types.h"
27
28 // Maximum number of allowed moves per position
29 const int MAX_MOVES = 256;
30
31 /// A move needs 16 bits to be stored
32 ///
33 /// bit  0- 5: destination square (from 0 to 63)
34 /// bit  6-11: origin square (from 0 to 63)
35 /// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2)
36 /// bit 14-15: special move flag: promotion (1), en passant (2), castle (3)
37 ///
38 /// Special cases are MOVE_NONE and MOVE_NULL. We can sneak these in
39 /// because in any normal move destination square is always different
40 /// from origin square while MOVE_NONE and MOVE_NULL have the same
41 /// origin and destination square, 0 and 1 respectively.
42
43 enum Move {
44   MOVE_NONE = 0,
45   MOVE_NULL = 65
46 };
47
48
49 struct MoveStack {
50   Move move;
51   int score;
52 };
53
54 inline bool operator<(const MoveStack& f, const MoveStack& s) { return f.score < s.score; }
55
56 // An helper insertion sort implementation, works with pointers and iterators
57 template<typename T, typename K>
58 inline void insertion_sort(K firstMove, K lastMove)
59 {
60     T value;
61     K cur, p, d;
62
63     if (firstMove != lastMove)
64         for (cur = firstMove + 1; cur != lastMove; cur++)
65         {
66             p = d = cur;
67             value = *p--;
68             if (*p < value)
69             {
70                 do *d = *p;
71                 while (--d != firstMove && *--p < value);
72                 *d = value;
73             }
74         }
75 }
76
77 // Our dedicated sort in range [firstMove, lastMove), first splits
78 // positive scores from ramining then order seaprately the two sets.
79 template<typename T>
80 inline void sort_moves(T* firstMove, T* lastMove, T** lastPositive)
81 {
82     T tmp;
83     T *p, *d;
84
85     d = lastMove;
86     p = firstMove - 1;
87
88     d->score = -1; // right guard
89
90     // Split positives vs non-positives
91     do {
92         while ((++p)->score > 0) {}
93
94         if (p != d)
95         {
96             while (--d != p && d->score <= 0) {}
97
98             tmp = *p;
99             *p = *d;
100             *d = tmp;
101         }
102
103     } while (p != d);
104
105     // Sort just positive scored moves, remaining only when we get there
106     insertion_sort<T, T*>(firstMove, p);
107     *lastPositive = p;
108 }
109
110 // Picks up the best move in range [curMove, lastMove), one per cycle.
111 // It is faster then sorting all the moves in advance when moves are few,
112 // as normally are the possible captures. Note that is not a stable alghoritm.
113 template<typename T>
114 inline T pick_best(T* curMove, T* lastMove)
115 {
116     T bestMove, tmp;
117
118     bestMove = *curMove;
119     while (++curMove != lastMove)
120     {
121         if (bestMove < *curMove)
122         {
123             tmp = *curMove;
124             *curMove = bestMove;
125             bestMove = tmp;
126         }
127     }
128     return bestMove;
129 }
130
131
132 inline Square move_from(Move m) {
133   return Square((m >> 6) & 0x3F);
134 }
135
136 inline Square move_to(Move m) {
137   return Square(m & 0x3F);
138 }
139
140 inline bool move_is_special(Move m) {
141   return m & (3 << 14);
142 }
143
144 inline bool move_is_promotion(Move m) {
145   return (m & (3 << 14)) == (1 << 14);
146 }
147
148 inline int move_is_ep(Move m) {
149   return (m & (3 << 14)) == (2 << 14);
150 }
151
152 inline int move_is_castle(Move m) {
153   return (m & (3 << 14)) == (3 << 14);
154 }
155
156 inline bool move_is_short_castle(Move m) {
157   return move_is_castle(m) && (move_to(m) > move_from(m));
158 }
159
160 inline bool move_is_long_castle(Move m) {
161   return move_is_castle(m) && (move_to(m) < move_from(m));
162 }
163
164 inline PieceType promotion_piece_type(Move m) {
165   return PieceType(((m >> 12) & 3) + 2);
166 }
167
168 inline Move make_move(Square from, Square to) {
169   return Move(to | (from << 6));
170 }
171
172 inline Move make_promotion_move(Square from, Square to, PieceType promotion) {
173   return Move(to | (from << 6) | ((promotion - 2) << 12) | (1 << 14));
174 }
175
176 inline Move make_ep_move(Square from, Square to) {
177   return Move(to | (from << 6) | (2 << 14));
178 }
179
180 inline Move make_castle_move(Square from, Square to) {
181   return Move(to | (from << 6) | (3 << 14));
182 }
183
184 inline bool move_is_ok(Move m) {
185   return move_from(m) != move_to(m); // Catches also MOVE_NONE
186 }
187
188 class Position;
189
190 extern const std::string move_to_uci(Move m, bool chess960);
191 extern Move move_from_uci(const Position& pos, const std::string& str);
192 extern const std::string move_to_san(Position& pos, Move m);
193 extern const std::string pretty_pv(Position& pos, int depth, Value score, int time, Move pv[]);
194
195 #endif // !defined(MOVE_H_INCLUDED)