Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
official-stockfish
GitHub Repository: official-stockfish/Stockfish
Path: blob/master/src/position.h
376 views
1
/*
2
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)
4
5
Stockfish is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9
10
Stockfish is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program. If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#ifndef POSITION_H_INCLUDED
20
#define POSITION_H_INCLUDED
21
22
#include <cassert>
23
#include <deque>
24
#include <iosfwd>
25
#include <memory>
26
#include <string>
27
28
#include "bitboard.h"
29
#include "types.h"
30
31
namespace Stockfish {
32
33
class TranspositionTable;
34
35
// StateInfo struct stores information needed to restore a Position object to
36
// its previous state when we retract a move. Whenever a move is made on the
37
// board (by calling Position::do_move), a StateInfo object must be passed.
38
39
struct StateInfo {
40
41
// Copied when making a move
42
Key materialKey;
43
Key pawnKey;
44
Key minorPieceKey;
45
Key nonPawnKey[COLOR_NB];
46
Value nonPawnMaterial[COLOR_NB];
47
int castlingRights;
48
int rule50;
49
int pliesFromNull;
50
Square epSquare;
51
52
// Not copied when making a move (will be recomputed anyhow)
53
Key key;
54
Bitboard checkersBB;
55
StateInfo* previous;
56
Bitboard blockersForKing[COLOR_NB];
57
Bitboard pinners[COLOR_NB];
58
Bitboard checkSquares[PIECE_TYPE_NB];
59
Piece capturedPiece;
60
int repetition;
61
};
62
63
64
// A list to keep track of the position states along the setup moves (from the
65
// start position to the position just before the search starts). Needed by
66
// 'draw by repetition' detection. Use a std::deque because pointers to
67
// elements are not invalidated upon list resizing.
68
using StateListPtr = std::unique_ptr<std::deque<StateInfo>>;
69
70
71
// Position class stores information regarding the board representation as
72
// pieces, side to move, hash keys, castling info, etc. Important methods are
73
// do_move() and undo_move(), used by the search to update node info when
74
// traversing the search tree.
75
class Position {
76
public:
77
static void init();
78
79
Position() = default;
80
Position(const Position&) = delete;
81
Position& operator=(const Position&) = delete;
82
83
// FEN string input/output
84
Position& set(const std::string& fenStr, bool isChess960, StateInfo* si);
85
Position& set(const std::string& code, Color c, StateInfo* si);
86
std::string fen() const;
87
88
// Position representation
89
Bitboard pieces() const; // All pieces
90
template<typename... PieceTypes>
91
Bitboard pieces(PieceTypes... pts) const;
92
Bitboard pieces(Color c) const;
93
template<typename... PieceTypes>
94
Bitboard pieces(Color c, PieceTypes... pts) const;
95
Piece piece_on(Square s) const;
96
Square ep_square() const;
97
bool empty(Square s) const;
98
template<PieceType Pt>
99
int count(Color c) const;
100
template<PieceType Pt>
101
int count() const;
102
template<PieceType Pt>
103
Square square(Color c) const;
104
105
// Castling
106
bool can_castle(CastlingRights cr) const;
107
bool castling_impeded(CastlingRights cr) const;
108
Square castling_rook_square(CastlingRights cr) const;
109
110
// Checking
111
Bitboard checkers() const;
112
Bitboard blockers_for_king(Color c) const;
113
Bitboard check_squares(PieceType pt) const;
114
Bitboard pinners(Color c) const;
115
116
// Attacks to/from a given square
117
Bitboard attackers_to(Square s) const;
118
Bitboard attackers_to(Square s, Bitboard occupied) const;
119
bool attackers_to_exist(Square s, Bitboard occupied, Color c) const;
120
void update_slider_blockers(Color c) const;
121
template<PieceType Pt>
122
Bitboard attacks_by(Color c) const;
123
124
// Properties of moves
125
bool legal(Move m) const;
126
bool pseudo_legal(const Move m) const;
127
bool capture(Move m) const;
128
bool capture_stage(Move m) const;
129
bool gives_check(Move m) const;
130
Piece moved_piece(Move m) const;
131
Piece captured_piece() const;
132
133
// Doing and undoing moves
134
void do_move(Move m, StateInfo& newSt, const TranspositionTable* tt);
135
DirtyPiece do_move(Move m, StateInfo& newSt, bool givesCheck, const TranspositionTable* tt);
136
void undo_move(Move m);
137
void do_null_move(StateInfo& newSt, const TranspositionTable& tt);
138
void undo_null_move();
139
140
// Static Exchange Evaluation
141
bool see_ge(Move m, int threshold = 0) const;
142
143
// Accessing hash keys
144
Key key() const;
145
Key material_key() const;
146
Key pawn_key() const;
147
Key minor_piece_key() const;
148
Key non_pawn_key(Color c) const;
149
150
// Other properties of the position
151
Color side_to_move() const;
152
int game_ply() const;
153
bool is_chess960() const;
154
bool is_draw(int ply) const;
155
bool is_repetition(int ply) const;
156
bool upcoming_repetition(int ply) const;
157
bool has_repeated() const;
158
int rule50_count() const;
159
Value non_pawn_material(Color c) const;
160
Value non_pawn_material() const;
161
162
// Position consistency check, for debugging
163
bool pos_is_ok() const;
164
void flip();
165
166
StateInfo* state() const;
167
168
void put_piece(Piece pc, Square s);
169
void remove_piece(Square s);
170
171
private:
172
// Initialization helpers (used while setting up a position)
173
void set_castling_right(Color c, Square rfrom);
174
void set_state() const;
175
void set_check_info() const;
176
177
// Other helpers
178
void move_piece(Square from, Square to);
179
template<bool Do>
180
void do_castling(Color us,
181
Square from,
182
Square& to,
183
Square& rfrom,
184
Square& rto,
185
DirtyPiece* const dp = nullptr);
186
Key adjust_key50(Key k) const;
187
188
// Data members
189
Piece board[SQUARE_NB];
190
Bitboard byTypeBB[PIECE_TYPE_NB];
191
Bitboard byColorBB[COLOR_NB];
192
int pieceCount[PIECE_NB];
193
int castlingRightsMask[SQUARE_NB];
194
Square castlingRookSquare[CASTLING_RIGHT_NB];
195
Bitboard castlingPath[CASTLING_RIGHT_NB];
196
StateInfo* st;
197
int gamePly;
198
Color sideToMove;
199
bool chess960;
200
};
201
202
std::ostream& operator<<(std::ostream& os, const Position& pos);
203
204
inline Color Position::side_to_move() const { return sideToMove; }
205
206
inline Piece Position::piece_on(Square s) const {
207
assert(is_ok(s));
208
return board[s];
209
}
210
211
inline bool Position::empty(Square s) const { return piece_on(s) == NO_PIECE; }
212
213
inline Piece Position::moved_piece(Move m) const { return piece_on(m.from_sq()); }
214
215
inline Bitboard Position::pieces() const { return byTypeBB[ALL_PIECES]; }
216
217
template<typename... PieceTypes>
218
inline Bitboard Position::pieces(PieceTypes... pts) const {
219
return (byTypeBB[pts] | ...);
220
}
221
222
inline Bitboard Position::pieces(Color c) const { return byColorBB[c]; }
223
224
template<typename... PieceTypes>
225
inline Bitboard Position::pieces(Color c, PieceTypes... pts) const {
226
return pieces(c) & pieces(pts...);
227
}
228
229
template<PieceType Pt>
230
inline int Position::count(Color c) const {
231
return pieceCount[make_piece(c, Pt)];
232
}
233
234
template<PieceType Pt>
235
inline int Position::count() const {
236
return count<Pt>(WHITE) + count<Pt>(BLACK);
237
}
238
239
template<PieceType Pt>
240
inline Square Position::square(Color c) const {
241
assert(count<Pt>(c) == 1);
242
return lsb(pieces(c, Pt));
243
}
244
245
inline Square Position::ep_square() const { return st->epSquare; }
246
247
inline bool Position::can_castle(CastlingRights cr) const { return st->castlingRights & cr; }
248
249
inline bool Position::castling_impeded(CastlingRights cr) const {
250
assert(cr == WHITE_OO || cr == WHITE_OOO || cr == BLACK_OO || cr == BLACK_OOO);
251
return pieces() & castlingPath[cr];
252
}
253
254
inline Square Position::castling_rook_square(CastlingRights cr) const {
255
assert(cr == WHITE_OO || cr == WHITE_OOO || cr == BLACK_OO || cr == BLACK_OOO);
256
return castlingRookSquare[cr];
257
}
258
259
inline Bitboard Position::attackers_to(Square s) const { return attackers_to(s, pieces()); }
260
261
template<PieceType Pt>
262
inline Bitboard Position::attacks_by(Color c) const {
263
264
if constexpr (Pt == PAWN)
265
return c == WHITE ? pawn_attacks_bb<WHITE>(pieces(WHITE, PAWN))
266
: pawn_attacks_bb<BLACK>(pieces(BLACK, PAWN));
267
else
268
{
269
Bitboard threats = 0;
270
Bitboard attackers = pieces(c, Pt);
271
while (attackers)
272
threats |= attacks_bb<Pt>(pop_lsb(attackers), pieces());
273
return threats;
274
}
275
}
276
277
inline Bitboard Position::checkers() const { return st->checkersBB; }
278
279
inline Bitboard Position::blockers_for_king(Color c) const { return st->blockersForKing[c]; }
280
281
inline Bitboard Position::pinners(Color c) const { return st->pinners[c]; }
282
283
inline Bitboard Position::check_squares(PieceType pt) const { return st->checkSquares[pt]; }
284
285
inline Key Position::key() const { return adjust_key50(st->key); }
286
287
inline Key Position::adjust_key50(Key k) const {
288
return st->rule50 < 14 ? k : k ^ make_key((st->rule50 - 14) / 8);
289
}
290
291
inline Key Position::pawn_key() const { return st->pawnKey; }
292
293
inline Key Position::material_key() const { return st->materialKey; }
294
295
inline Key Position::minor_piece_key() const { return st->minorPieceKey; }
296
297
inline Key Position::non_pawn_key(Color c) const { return st->nonPawnKey[c]; }
298
299
inline Value Position::non_pawn_material(Color c) const { return st->nonPawnMaterial[c]; }
300
301
inline Value Position::non_pawn_material() const {
302
return non_pawn_material(WHITE) + non_pawn_material(BLACK);
303
}
304
305
inline int Position::game_ply() const { return gamePly; }
306
307
inline int Position::rule50_count() const { return st->rule50; }
308
309
inline bool Position::is_chess960() const { return chess960; }
310
311
inline bool Position::capture(Move m) const {
312
assert(m.is_ok());
313
return (!empty(m.to_sq()) && m.type_of() != CASTLING) || m.type_of() == EN_PASSANT;
314
}
315
316
// Returns true if a move is generated from the capture stage, having also
317
// queen promotions covered, i.e. consistency with the capture stage move
318
// generation is needed to avoid the generation of duplicate moves.
319
inline bool Position::capture_stage(Move m) const {
320
assert(m.is_ok());
321
return capture(m) || m.promotion_type() == QUEEN;
322
}
323
324
inline Piece Position::captured_piece() const { return st->capturedPiece; }
325
326
inline void Position::put_piece(Piece pc, Square s) {
327
328
board[s] = pc;
329
byTypeBB[ALL_PIECES] |= byTypeBB[type_of(pc)] |= s;
330
byColorBB[color_of(pc)] |= s;
331
pieceCount[pc]++;
332
pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
333
}
334
335
inline void Position::remove_piece(Square s) {
336
337
Piece pc = board[s];
338
byTypeBB[ALL_PIECES] ^= s;
339
byTypeBB[type_of(pc)] ^= s;
340
byColorBB[color_of(pc)] ^= s;
341
board[s] = NO_PIECE;
342
pieceCount[pc]--;
343
pieceCount[make_piece(color_of(pc), ALL_PIECES)]--;
344
}
345
346
inline void Position::move_piece(Square from, Square to) {
347
348
Piece pc = board[from];
349
Bitboard fromTo = from | to;
350
byTypeBB[ALL_PIECES] ^= fromTo;
351
byTypeBB[type_of(pc)] ^= fromTo;
352
byColorBB[color_of(pc)] ^= fromTo;
353
board[from] = NO_PIECE;
354
board[to] = pc;
355
}
356
357
inline void Position::do_move(Move m, StateInfo& newSt, const TranspositionTable* tt = nullptr) {
358
do_move(m, newSt, gives_check(m), tt);
359
}
360
361
inline StateInfo* Position::state() const { return st; }
362
363
} // namespace Stockfish
364
365
#endif // #ifndef POSITION_H_INCLUDED
366
367