ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) { assert(pos.checkers()); Color us = pos.side_to_move(); Square ksq = pos.square<KING>(us); Bitboard sliderAttacks = 0; Bitboard sliders = pos.checkers() & ~pos.pieces(KNIGHT, PAWN); // Find all the squares attacked by slider checkers. We will remove them from // the king evasions in order to skip known illegal moves, which avoids any // useless legality checks later on. while (sliders) { Square checksq = pop_lsb(&sliders); sliderAttacks |= LineBB[checksq][ksq] ^ checksq; } // Generate evasions for king, capture and non capture moves Bitboard b = pos.attacks_from<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks; while (b) *moveList++ = make_move(ksq, pop_lsb(&b)); if (more_than_one(pos.checkers())) return moveList; // Double check, only a king move can save the day // Generate blocking evasions or captures of the checking piece Square checksq = lsb(pos.checkers()); Bitboard target = between_bb(checksq, ksq) | checksq; return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, moveList, target) : generate_all<BLACK, EVASIONS>(pos, moveList, target); }
ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) { assert(!pos.checkers()); Color us = pos.side_to_move(); CheckInfo ci(pos); Bitboard dc = ci.dcCandidates; while (dc) { Square from = pop_lsb(&dc); PieceType pt = type_of(pos.piece_on(from)); if (pt == PAWN) continue; // Will be generated together with direct checks Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces(); if (pt == KING) b &= ~PseudoAttacks[QUEEN][ci.ksq]; while (b) *moveList++ = make_move(from, pop_lsb(&b)); } return us == WHITE ? generate_all<WHITE, QUIET_CHECKS>(pos, moveList, ~pos.pieces(), &ci) : generate_all<BLACK, QUIET_CHECKS>(pos, moveList, ~pos.pieces(), &ci); }
ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) { assert(!pos.checkers()); Color us = pos.side_to_move(); Bitboard dc = pos.blockers_for_king(~us) & pos.pieces(us); while (dc) { Square from = pop_lsb(&dc); PieceType pt = type_of(pos.piece_on(from)); if (pt == PAWN) continue; // Will be generated together with direct checks Bitboard b = pos.attacks_from(pt, from) & ~pos.pieces(); if (pt == KING) b &= ~PseudoAttacks[QUEEN][pos.square<KING>(~us)]; while (b) *moveList++ = make_move(from, pop_lsb(&b)); } return us == WHITE ? generate_all<WHITE, QUIET_CHECKS>(pos, moveList, ~pos.pieces()) : generate_all<BLACK, QUIET_CHECKS>(pos, moveList, ~pos.pieces()); }
static Key polyglot_key(const Pos *pos) { Key key = 0; Bitboard b = pieces(); while (b) { Square s = pop_lsb(&b); Piece p = piece_on(s); // PolyGlot pieces are: BP = 0, WP = 1, BN = 2, ... BK = 10, WK = 11 key ^= PG.Zobrist.psq[2 * (type_of_p(p) - 1) + (color_of(p) == WHITE)][s]; } b = can_castle_any(); while (b) key ^= PG.Zobrist.castle[pop_lsb(&b)]; if (ep_square()) key ^= PG.Zobrist.enpassant[file_of(ep_square())]; if (pos_stm() == WHITE) key ^= PG.Zobrist.turn; return key; }
MoveStack* generate<QUIET_CHECKS>(const Position& pos, MoveStack* mlist) { assert(!pos.checkers()); CheckInfo ci(pos); Bitboard dc = ci.dcCandidates; while (dc) { Square from = pop_lsb(&dc); PieceType pt = type_of(pos.piece_on(from)); if (pt == PAWN) continue; // Will be generated togheter with direct checks Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces(); if (pt == KING) b &= ~PseudoAttacks[QUEEN][ci.ksq]; SERIALIZE(b); } return generate_all<QUIET_CHECKS>(pos, mlist, pos.side_to_move(), ~pos.pieces(), &ci); }
MoveStack* generate<EVASIONS>(const Position& pos, MoveStack* mlist) { assert(pos.checkers()); Square from, checksq; int checkersCnt = 0; Color us = pos.side_to_move(); Square ksq = pos.king_square(us); Bitboard sliderAttacks = 0; Bitboard b = pos.checkers(); assert(pos.checkers()); // Find squares attacked by slider checkers, we will remove them from the king // evasions so to skip known illegal moves avoiding useless legality check later. do { checkersCnt++; checksq = pop_lsb(&b); assert(color_of(pos.piece_on(checksq)) == ~us); switch (type_of(pos.piece_on(checksq))) { case BISHOP: sliderAttacks |= PseudoAttacks[BISHOP][checksq]; break; case ROOK: sliderAttacks |= PseudoAttacks[ROOK][checksq]; break; case QUEEN: // If queen and king are far or not on a diagonal line we can safely // remove all the squares attacked in the other direction becuase are // not reachable by the king anyway. if (between_bb(ksq, checksq) || !(PseudoAttacks[BISHOP][checksq] & ksq)) sliderAttacks |= PseudoAttacks[QUEEN][checksq]; // Otherwise we need to use real rook attacks to check if king is safe // to move in the other direction. For example: king in B2, queen in A1 // a knight in B1, and we can safely move to C1. else sliderAttacks |= PseudoAttacks[BISHOP][checksq] | pos.attacks_from<ROOK>(checksq); default: break; } } while (b); // Generate evasions for king, capture and non capture moves b = pos.attacks_from<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks; from = ksq; SERIALIZE(b); if (checkersCnt > 1) return mlist; // Double check, only a king move can save the day // Generate blocking evasions or captures of the checking piece Bitboard target = between_bb(checksq, ksq) | pos.checkers(); return generate_all<EVASIONS>(pos, mlist, us, target); }
ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* mlist) { assert(pos.checkers()); int checkersCnt = 0; Color us = pos.side_to_move(); Square ksq = pos.king_square(us), from = ksq /* For SERIALIZE */, checksq; Bitboard sliderAttacks = 0; Bitboard b = pos.checkers(); assert(pos.checkers()); // Find all the squares attacked by slider checkers. We will remove them from // the king evasions in order to skip known illegal moves, which avoids any // useless legality checks later on. do { ++checkersCnt; checksq = pop_lsb(&b); assert(color_of(pos.piece_on(checksq)) == ~us); if (type_of(pos.piece_on(checksq)) > KNIGHT) // A slider sliderAttacks |= LineBB[checksq][ksq] ^ checksq; } while (b); // Generate evasions for king, capture and non capture moves b = pos.attacks_from<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks; SERIALIZE(b); if (checkersCnt > 1) return mlist; // Double check, only a king move can save the day // Generate blocking evasions or captures of the checking piece Bitboard target = between_bb(checksq, ksq) | checksq; return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, mlist, target) : generate_all<BLACK, EVASIONS>(pos, mlist, target); }
MoveStack* generate<QUIET_CHECKS>(const Position& pos, MoveStack* mlist) { assert(!pos.in_check()); Color us = pos.side_to_move(); CheckInfo ci(pos); Bitboard dc = ci.dcCandidates; while (dc) { Square from = pop_lsb(&dc); PieceType pt = type_of(pos.piece_on(from)); if (pt == PAWN) continue; // Will be generated togheter with direct checks Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces(); if (pt == KING) b &= ~PseudoAttacks[QUEEN][ci.ksq]; SERIALIZE(b); } mlist = (us == WHITE ? generate_pawn_moves<WHITE, QUIET_CHECKS>(pos, mlist, ci.dcCandidates, ci.ksq) : generate_pawn_moves<BLACK, QUIET_CHECKS>(pos, mlist, ci.dcCandidates, ci.ksq)); mlist = generate_direct_checks<KNIGHT>(pos, mlist, us, ci); mlist = generate_direct_checks<BISHOP>(pos, mlist, us, ci); mlist = generate_direct_checks<ROOK>(pos, mlist, us, ci); mlist = generate_direct_checks<QUEEN>(pos, mlist, us, ci); if (pos.can_castle(us)) { mlist = generate_castle<KING_SIDE, true>(pos, mlist, us); mlist = generate_castle<QUEEN_SIDE, true>(pos, mlist, us); } return mlist; }