-
- // Find all attackers to the destination square, with the moving piece
- // removed, but possibly an X-ray attacker added behind it.
- clear_bit(&occupied, from);
- attackers = (rook_attacks_bb(to, occupied) & pieces(ROOK, QUEEN))
- | (bishop_attacks_bb(to, occupied)& pieces(BISHOP, QUEEN))
- | (attacks_from<KNIGHT>(to) & pieces(KNIGHT))
- | (attacks_from<KING>(to) & pieces(KING))
- | (attacks_from<PAWN>(to, WHITE) & pieces(PAWN, BLACK))
- | (attacks_from<PAWN>(to, BLACK) & pieces(PAWN, WHITE));
-
- // If the opponent has no attackers we are finished
- stm = opposite_color(color_of_piece_on(from));
- stmAttackers = attackers & pieces_of_color(stm);
- if (!stmAttackers)
- return seeValues[capturedType];
-
- // The destination square is defended, which makes things rather more
- // difficult to compute. We proceed by building up a "swap list" containing
- // the material gain or loss at each stop in a sequence of captures to the
- // destination square, where the sides alternately capture, and always
- // capture with the least valuable piece. After each capture, we look for
- // new X-ray attacks from behind the capturing piece.
- swapList[0] = seeValues[capturedType];
- capturedType = type_of_piece_on(from);
-
- do {
- // Locate the least valuable attacker for the side to move. The loop
- // below looks like it is potentially infinite, but it isn't. We know
- // that the side to move still has at least one attacker left.
- for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
- assert(pt < KING);
-
- // Remove the attacker we just found from the 'occupied' bitboard,
- // and scan for new X-ray attacks behind the attacker.
- b = stmAttackers & pieces(pt);
- occupied ^= (b & (~b + 1));
- attackers |= (rook_attacks_bb(to, occupied) & pieces(ROOK, QUEEN))
- | (bishop_attacks_bb(to, occupied) & pieces(BISHOP, QUEEN));
-
- attackers &= occupied; // Cut out pieces we've already done
-
- // Add the new entry to the swap list
- assert(slIndex < 32);
- swapList[slIndex] = -swapList[slIndex - 1] + seeValues[capturedType];
- slIndex++;
-
- // Remember the value of the capturing piece, and change the side to
- // move before beginning the next iteration.
- capturedType = pt;
- stm = opposite_color(stm);
- stmAttackers = attackers & pieces_of_color(stm);
-
- // Stop before processing a king capture
- if (capturedType == KING && stmAttackers)
- {
- assert(slIndex < 32);
- swapList[slIndex++] = QueenValueMidgame*10;
- break;
- }
- } while (stmAttackers);
-
- // Having built the swap list, we negamax through it to find the best
- // achievable score from the point of view of the side to move.
- while (--slIndex)
- swapList[slIndex-1] = Min(-swapList[slIndex], swapList[slIndex-1]);
-
- return swapList[0];
-}
-
-
-/// Position::clear() erases the position object to a pristine state, with an
-/// empty board, white to move, and no castling rights.
-
-void Position::clear() {
-
- st = &startState;
- memset(st, 0, sizeof(StateInfo));
- st->epSquare = SQ_NONE;
- startPosPlyCounter = 0;
- nodes = 0;
-
- memset(byColorBB, 0, sizeof(Bitboard) * 2);
- memset(byTypeBB, 0, sizeof(Bitboard) * 8);
- memset(pieceCount, 0, sizeof(int) * 2 * 8);
- memset(index, 0, sizeof(int) * 64);
-
- for (int i = 0; i < 64; i++)
- board[i] = PIECE_NONE;
-
- for (int i = 0; i < 8; i++)
- for (int j = 0; j < 16; j++)
- pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE;
-
- for (Square sq = SQ_A1; sq <= SQ_H8; sq++)
- castleRightsMask[sq] = ALL_CASTLES;
-
- sideToMove = WHITE;
- initialKFile = FILE_E;
- initialKRFile = FILE_H;
- initialQRFile = FILE_A;
-}
-
-
-/// Position::put_piece() puts a piece on the given square of the board,
-/// updating the board array, pieces list, bitboards, and piece counts.
-
-void Position::put_piece(Piece p, Square s) {
-
- Color c = color_of_piece(p);
- PieceType pt = type_of_piece(p);
-
- board[s] = p;
- index[s] = pieceCount[c][pt]++;
- pieceList[c][pt][index[s]] = s;
-
- set_bit(&(byTypeBB[pt]), s);
- set_bit(&(byColorBB[c]), s);
- set_bit(&(byTypeBB[0]), s); // HACK: byTypeBB[0] contains all occupied squares.
-}
-
-
-/// Position::compute_key() computes the hash key of the position. The hash
-/// key is usually updated incrementally as moves are made and unmade, the
-/// compute_key() function is only used when a new position is set up, and
-/// to verify the correctness of the hash key when running in debug mode.
-
-Key Position::compute_key() const {
-
- Key result = zobCastle[st->castleRights];
-
- for (Square s = SQ_A1; s <= SQ_H8; s++)
- if (square_is_occupied(s))
- result ^= zobrist[color_of_piece_on(s)][type_of_piece_on(s)][s];
-
- if (ep_square() != SQ_NONE)
- result ^= zobEp[ep_square()];
-
- if (side_to_move() == BLACK)
- result ^= zobSideToMove;
-
- return result;
-}
-
-
-/// Position::compute_pawn_key() computes the hash key of the position. The
-/// hash key is usually updated incrementally as moves are made and unmade,
-/// the compute_pawn_key() function is only used when a new position is set
-/// up, and to verify the correctness of the pawn hash key when running in
-/// debug mode.
-
-Key Position::compute_pawn_key() const {
-
- Bitboard b;
- Key result = 0;
-
- for (Color c = WHITE; c <= BLACK; c++)