39 ASSERT(color == 0 || color == 1);
40 ASSERT(piece_type > 0 && piece_type < 8);
43 ++n_[
color][piece_type];
48 ASSERT(color == 0 || color == 1);
49 ASSERT(piece_type > 0 && piece_type < 8);
52 --n_[
color][piece_type];
57 ASSERT(color == 0 || color == 1);
64 ASSERT(color == 0 || color == 1);
65 ASSERT(piece_type > 0 && piece_type < 8);
67 return n_[
color][piece_type];
71 const int8_t* a = n_[0];
72 const int8_t* b_ptr = b.n_[0];
73 return std::equal(a, a + 16, b_ptr);
94 ASSERT(color == 0 || color == 1);
95 ASSERT(idx >= 0 && idx < 16);
97 return pieces_[
color][idx].piece_type;
102 ASSERT(color == 0 || color == 1);
103 ASSERT(idx >= 0 && idx < 16);
105 return pieces_[
color][idx].sq;
110 ASSERT(color == 0 || color == 1);
111 ASSERT(idx >= 0 && idx < 16);
113 pieces_[
color][idx].sq = to;
118 ASSERT(color == 0 || color == 1);
119 ASSERT(idx >= 0 && idx < 16);
121 pieces_[
color][idx].piece_type = piece_type;
129 ASSERT(color == 0 || color == 1);
130 ASSERT(removed_idx >= 0 && removed_idx < 16);
131 ASSERT(lastvalid_idx >= 0 && lastvalid_idx < 16);
133 pieces_[
color][removed_idx] = pieces_[
color][lastvalid_idx];
134 return pieces_[
color][lastvalid_idx].sq;
139 ASSERT(color == 0 || color == 1);
140 ASSERT(idx >= 0 && idx < 16);
141 ASSERT(piece_type !=
KING || idx == getKingIdx());
144 pieces_[
color][idx].piece_type = piece_type;
153 enum { EMPTY_SQ_ = 0xFF };
166 std::fill_n(board_, 64, EMPTY_SQ_);
171 for (uint8_t idx = 0; idx < 16; ++idx) {
172 if (idx < pos_count) {
175 pieces_.
set(
color, idx, sq, piece_type);
189 for (
int idx = 0, n = mt_.
count(
WHITE); idx < n; ++idx) {
195 for (
int idx = 0, n = mt_.
count(
BLACK); idx < n; ++idx) {
219 squareT king_to, rook_from, rook_to;
221 king_to = black +
G1;
222 rook_from = black +
H1;
223 rook_to = black +
F1;
225 king_to = black +
C1;
226 rook_from = black +
A1;
227 rook_to = black +
D1;
229 const uint8_t rook_idx = board_[rook_from];
234 board_[rook_to] = rook_idx;
235 board_[king_to] = king_idx;
236 board_[rook_from] = EMPTY_SQ_;
237 board_[king_from] = EMPTY_SQ_;
241 template <colorT color>
249 board_[from] = EMPTY_SQ_;
251 return remove<1 -
color>(to, idx);
254 template <colorT color>
256 const uint8_t oldIdx = board_[
sq];
258 if (oldIdx == EMPTY_SQ_)
264 if (oldIdx != lastvalid_idx) {
266 board_[moved_sq] = oldIdx;
283 if (lastPt ==
PAWN) {
286 }
else if (mt_.
count(lastCol, lastPt) > 1) {
287 int ambiguity = ambiguousMove(lastFrom, lastTo, lastCol, lastPt);
296 bool direct_check = lastPt !=
KING && movegen::attack<uint8_t>(
297 lastTo, enemyKingSq, lastCol,
298 lastPt, board_, EMPTY_SQ_);
300 find_attacker_slider(enemyKingSq, lastCol) >= 0) {
319 const squareT kingSq = getKingSquare(lastCol);
321 for (
int i = 1, n = mt_.
count(lastCol); i < n; i++) {
322 if (getPiece(lastCol, i) != lastPt)
329 board_[lastFrom] = board_[
sq];
330 board_[
sq] = EMPTY_SQ_;
332 bool pseudoLegal = movegen::pseudo<uint8_t>(
333 sq, lastTo, lastCol, lastPt, board_, EMPTY_SQ_);
335 std::pair<pieceT, squareT> pin;
337 pin = movegen::opens_ray<uint8_t>(
sq, lastTo, kingSq, board_,
339 board_[
sq] = board_[lastFrom];
340 board_[lastFrom] = EMPTY_SQ_;
346 uint8_t idx = board_[pin.second];
347 if (idx != EMPTY_SQ_ && idx < mt_.
count(enemyCol) &&
348 getSquare(enemyCol, idx) == pin.second) {
349 const pieceT pt = getPiece(enemyCol, idx);
350 if (pt ==
QUEEN || pt == pin.first)
372 for (
int idx = 0, n = mt_.
count(color); idx < n; ++idx) {
373 const pieceT pt = getPiece(color, idx);
378 if (movegen::attack_slider<uint8_t>(sq, destSq, pt, board_,
395 const byte* v_it = v_begin;
396 while (v_it < v_end) {
399 if (v_it >= v_end)
break;
400 byte haveFEN = *v_it++ & 1;
404 const char* FENstring = (
char*) v_it;
405 while (v_it < v_end) {
406 if (*v_it++ == 0)
return FastGame(FENstring, v_it, v_end);
410 }
else if (b == 255) {
415 if (v_it < v_end) v_it += *v_it +1;
423 for (
int ply=0; ply <= ply_to_skip; ply++, cToMove_ = 1 - cToMove_) {
425 ? DecodeNextMove<FullMove, WHITE>()
426 : DecodeNextMove<FullMove, BLACK>();
430 if (ply == ply_to_skip) {
432 cToMove_ = 1 - cToMove_;
440 std::stringstream res;
441 for (
int ply=0; ply < ply_to_skip +
count; ply++, cToMove_ = 1 - cToMove_) {
443 if (cToMove_ ==
WHITE) {
444 move = DecodeNextMove <FullMove, WHITE>();
447 if (ply < ply_to_skip)
continue;
448 if (ply > ply_to_skip) res <<
" ";
449 res << (1 + ply/2) <<
".";
451 move = DecodeNextMove <FullMove, BLACK>();
454 if (ply < ply_to_skip)
continue;
455 if (ply == ply_to_skip) res << (1 + ply/2) <<
"...";
464 template <colorT toMove>
472 const auto captured_pt =
move.getCaptured();
476 if (a.
count(color) < b.count(color))
480 b.count(color,
PAWN) + b.count(color, captured_pt);
483 if (cToMove_ != toMove) {
484 const auto move = DecodeNextMove<
FullMove, 1 - toMove>();
490 if (board_.
isEqual(board, mt_count))
494 const auto move = DecodeNextMove<FullMove, toMove>();
495 if (less_material(board_.
materialCount(), mt_count, 1 - toMove,
500 const auto move = DecodeNextMove<
FullMove, 1 - toMove>();
513 : v_it_ (v_it), v_end_(v_end), cToMove_(
WHITE) {
518 : v_it_ (v_it), v_end_(v_end) {
521 board_.
Init(StartPos);
525 template <
typename TResult, colorT toMove>
526 TResult DecodeNextMove() {
530 while (v_it_ < v_end_) {
532 if (b < ENCODE_FIRST || b >
ENCODE_LAST)
return doPly<TResult, toMove>(b);
538 if (v_it_ >= v_end_)
return {};
545 }
while (nestCount > 0);
551 template <
typename TResult, colorT toMove> TResult doPly(
byte v) {
552 byte idx_piece_moving = v >> 4;
558 bool enPassant =
false;
559 switch (moving_piece) {
561 to = decodePawn<toMove>(from,
move,
promo, enPassant);
564 to = decodeBishop(from, move);
567 to = decodeKnight(from, move);
574 to = decodeQueen2byte(*v_it_++);
579 to = decodeRook(from, move);
583 return TResult(toMove, 0, 0,
KING);
586 to = decodeKing(from, move);
591 return TResult(toMove, from, rook_from);
599 if (to < 0 || to > 63)
603 TResult res(toMove, from, to, moving_piece);
607 res.setCapture(captured,
false);
608 }
else if (enPassant) {
610 captured = board_.
remove<1 - toMove>(0x3F &
sq);
611 res.setCapture(captured,
true);
631 static inline int decodeKing(
squareT from,
byte val) {
633 static const int8_t sqdiff[] = {0, -9, -8, -7, -1, 1, 7, 8, 9};
634 return from + sqdiff[val];
636 static inline int decodeQueen2byte(
byte val) {
639 static inline int decodeBishop(
squareT from,
byte val) {
641 return (val >= 8) ? from - 7 * fylediff
642 : from + 9 * fylediff;
644 static inline int decodeKnight(
squareT from,
byte val) {
646 static const int8_t sqdiff[] = {0, -17, -15, -10, -6, 6, 10, 15, 17, 0, 0, 0, 0, 0, 0, 0};
647 return from + sqdiff[val];
649 static inline int decodeRook(
squareT from,
byte val) {
656 template <colorT color>
660 static const int8_t sqdiff [] = { 7,8,9, 7,8,9, 7,8,9, 7,8,9, 7,8,9, 16 };
661 static const pieceT promoPieceFromVal [] = {
662 0,0,0,
QUEEN,
QUEEN,
QUEEN,
ROOK,
ROOK,
ROOK,
BISHOP,
BISHOP,
BISHOP,
KNIGHT,
KNIGHT,
KNIGHT,0
664 promo = promoPieceFromVal[val];
665 enPassant = (val == 0 || val == 2);
667 : from - sqdiff[val];
int search(const byte *board, const MaterialCount &mt_count)
pieceT piece_Type(pieceT p)
FullMove getMove(int ply_to_skip)
void promote(colorT color, int idx, pieceT piece_type)
Change the type of the piece with index idx.
int8_t count(colorT color, pieceT piece_type) const
Return the number of pieces of the specified color and type.
const MaterialCount & materialCount() const
static const Position & getStdStart()
constexpr size_t MAX_TAG_LEN
squareT getSquare(colorT color, int idx) const
pieceT getPieceType(colorT color, int idx) const
Return the type of the piece with index idx.
rankT square_Rank(squareT sq)
int8_t count(colorT color) const
Return the total number of pieces of the specified color.
errorT ReadFromFEN(const char *s)
const squareT * GetList(colorT c) const
pieceT remove(squareT sq, uint8_t newIdx=EMPTY_SQ_)
pieceT GetPiece(squareT sq) const
colorT color_Flip(colorT c)
squareT square_Make(fyleT f, rankT r)
static FastGame Create(const byte *v_begin, const byte *v_end)
const pieceT INVALID_PIECE
void decr(colorT color, pieceT piece_type)
Subtract one piece.
int8_t getKingIdx() const
SCID4 encoded games must use index 0 for kings.
pieceT move(uint8_t idx, squareT to, pieceT promo)
void set(colorT color, int idx, squareT sq, pieceT piece_type)
Set the type and square of the piece with index idx.
std::string getMoveSAN(int ply_to_skip, int count)
void setAmbiguity(bool fyle, bool rank)
bool isEqual(const pieceT *board, const MaterialCount &mt_count) const
pieceT getPiece(colorT color, int idx) const
bool operator==(const MaterialCount &b) const
squareT castle(bool king_side)
bool operator!=(const MaterialCount &b) const
Store the number of pieces for each type and color.
squareT getSquare(colorT color, int idx) const
Return the square position of the piece with index idx.
#define ENCODE_START_MARKER
void move(colorT color, int idx, squareT to)
Change the square position of the piece with index idx.
Implements functions for the validation of chess moves.
squareT remove(colorT color, int removed_idx, int lastvalid_idx)
Remove the piece with index removed_idx.
pieceT piece_Make(colorT c, pieceT p)
uint GetCount(colorT c) const
Store the type and position of the pieces compatibly with the SCID4 coding.
void fillSANInfo(FullMove &lastmove)
Given the actual board position, find if the last move needs to be made unambiguous and if it gives c...
void incr(colorT color, pieceT piece_type)
Add one piece.
fyleT square_Fyle(squareT sq)
std::string getSAN(colorT *toMove=0) const
#define ENCODE_END_MARKER